Revert "集成获取mdm分发通用数据格式接口集成"
This reverts commit 7f5df0954989899974bdb891fde11431b7048e9f.
已修改1个文件
已删除9个文件
已添加648个文件
¶Ô±ÈÐÂÎļþ |
| | |
| | | # http://editorconfig.org |
| | | root = true |
| | | |
| | | # ç©ºæ ¼æ¿ä»£Tab缩è¿å¨åç§ç¼è¾å·¥å
·ä¸ææä¸è´ |
| | | [*] |
| | | indent_style = space |
| | | indent_size = 4 |
| | | charset = utf-8 |
| | | end_of_line = lf |
| | | trim_trailing_whitespace = true |
| | | insert_final_newline = true |
| | | |
| | | [*.java] |
| | | indent_style = tab |
| | | |
| | | [*.{json,yml}] |
| | | indent_size = 2 |
| | | |
| | | [*.md] |
| | | insert_final_newline = false |
| | | trim_trailing_whitespace = false |
¶Ô±ÈÐÂÎļþ |
| | |
| | | # maven # |
| | | target |
| | | |
| | | logs |
| | | |
| | | # windows # |
| | | Thumbs.db |
| | | |
| | | # Mac # |
| | | .DS_Store |
| | | |
| | | # eclipse # |
| | | .settings |
| | | .project |
| | | .classpath |
| | | .log |
| | | *.class |
| | | |
| | | # idea # |
| | | .idea |
| | | *.iml |
| | | |
| | | # Package Files # |
| | | *.jar |
| | | *.war |
| | | *.ear |
| | | /target |
¶Ô±ÈÐÂÎļþ |
| | |
| | | BladeXå䏿æè®¸å¯åè®® |
| | | |
| | | ä¸ã ç¥è¯äº§æï¼ |
| | | BladeXç³»å产åç¥è¯äº§æå½ä¸æµ·å¸é·å¾·ç§ææéå
¬å¸ç¬ç«ææ |
| | | |
| | | äºã 许å¯ï¼ |
| | | 1. 卿¨å®å
¨æ¥åå¹¶éµå®æ¬åè®®çåºç¡ä¸ï¼æ¬åè®®æäºæ¨ä½¿ç¨BladeXçæäºæå©åéç¬å æ§è®¸å¯ã |
| | | 2. æ¬åè®®ä¸ï¼å°æ¬äº§å使ç¨ç¨éå为âä¸ä¸çç¨éâåâä¼ä¸çç¨éâã |
| | | 3. âä¸ä¸çç¨éâå®ä¹ï¼æä¸ªäººå¨éå¢ä½æºæä¸åºäºä»»ä½ç®çä½¿ç¨æ¬äº§åï¼ä»»ä½ç®çå
æ¬åä¸ç®çæéçå©ç®çï¼ã |
| | | 4. âä¼ä¸çç¨éâå®ä¹ï¼æå¢ä½æºæï¼ä¾å¦å
¬å¸ä¼ä¸ãæ¿åºã妿 ¡ãåéãå»é¢ã社ä¼å¢ä½çåç±»ç»ç»ï¼ï¼ä¸å
å«éå¢ï¼è¥éå¢ä½¿ç¨åé为å个åå
¬å¸åå«è´ä¹°ä¼ä¸ææï¼åºäºä»»ä½ç®çä½¿ç¨æ¬äº§åï¼ä»»ä½ç®çå
æ¬åä¸ç®çæéçå©ç®çï¼ã |
| | | |
| | | ä¸ã 约æåéå¶ï¼ |
| | | 1. æ¬äº§ååªè½ç±æ¨ä¸ºæ¬å议许å¯çç®çè使ç¨ï¼æ¨ä¸å¾éé²ç»ä»»ä½ç¬¬ä¸æ¹ï¼ |
| | | 2. 仿¬äº§ååå¾çä»»ä½ä¿¡æ¯ã软件ãäº§åææå¡ï¼æ¨ä¸å¾å¯¹å
¶è¿è¡ä¿®æ¹ãæ¹ç¼æåºäºä»¥ä¸å
容å建åç§ç±»å«çè¡ç产åå¹¶å®åã |
| | | 3. æ¨ä¸å¾å¯¹æ¬äº§å以åä¸ä¹å
³èçå䏿æè¿è¡åå¸ãåºç§ãéå®ãåéãæµæ¼ã转让ãè®¸å¯æåæ¾å许å¯è¯ã |
| | | 4. æ¬äº§åå䏿æçå¯è½å
å«ä¸äºç¬ç«åè½æç¹æ§ï¼è¿äºåè½åªæå¨æ¨è´ä¹°å䏿æåæå¯ä»¥ä½¿ç¨ã卿ªåå¾å䏿æçæ
åµä¸ï¼æ¨ä¸å¾ä½¿ç¨ãå°è¯ä½¿ç¨æå¤å¶è¿äºææçç¬ç«åè½ã |
| | | 5. è¥æ¨ç客æ·è¦æ±ä»¥æºç æ¹å¼äº¤ä»è½¯ä»¶ï¼é缴纳ä¼ä¸çææè´¹ç¨ï¼å¦åæ¬äº§åé¨åä¸å¾æä¾æºç ã |
| | | |
| | | åã ä¸å¾ç¨äºéæ³æç¦æ¢çç¨éï¼ |
| | | æ¨å¨ä½¿ç¨æ¬äº§åææå¡æ¶ï¼ä¸å¾å°æ¬äº§åäº§åææå¡ç¨äºä»»ä½éæ³ç¨éææ¬åè®®æ¡æ¬¾ãæ¡ä»¶å声æç¦æ¢çç¨éã |
| | | |
| | | äºã å
责说æï¼ |
| | | 1. æ¬äº§åæâç°ç¶âæäºè®¸å¯ï¼æ¨é¡»èªè¡æ¿æ
ä½¿ç¨æ¬äº§åçé£é©ãBladeXå¢éä¸å¯¹æ¤æä¾ä»»ä½æç¤ºãæç¤ºæä»»ä½å
¶å®å½¢å¼çæ
ä¿å表示ãå¨ä»»ä½æ
åµä¸ï¼å¯¹äºå ä½¿ç¨ææ æ³ä½¿ç¨æ¬è½¯ä»¶è导è´ç任使失ï¼å
æ¬ä½ä¸ä»
éäºåä¸å©æ¶¦æå¤±ãä¸å¡ä¸ææä¸å¡ä¿¡æ¯ä¸¢å¤±ï¼ï¼BladeXå¢éæ é忍æä»»ä½ç¬¬ä¸æ¹è´è´£ï¼å³ä½¿BladeXå¢é已被åç¥å¯è½ä¼é ææ¤ç±»æå¤±ãå¨ä»»ä½æ
åµä¸ï¼ BladeXå¢éåä¸å°±ä»»ä½ç´æ¥çãé´æ¥çãé带çãåææ§çãç¹å«çãæ©ææ§çåå¤ç½æ§çæå®³èµå¿æ¿æ
ä»»ä½è´£ä»»ï¼æ è®ºè¯¥ä¸»å¼ æ¯åºäºä¿è¯ãååãä¾µæï¼å
æ¬çå¿½ï¼ææ¯åºäºå
¶ä»åå ä½åºã |
| | | 2. æ¬äº§åå¯è½å
ç½®æç¬¬ä¸æ¹æå¡ï¼æ¨åºèªè¡è¯ä¼°ä½¿ç¨è¿äºç¬¬ä¸æ¹æå¡çé£é©ï¼ç±ä½¿ç¨æ¤ç±»ç¬¬ä¸æ¹æå¡è产çççº çº·ï¼å
¨é¨è´£ä»»ç±æ¨èªè¡æ¿æ
ã |
| | | 3. BladeXå¢éä¸å¯¹ä½¿ç¨æ¬äº§åæå»ºçç½ç«ä¸ä»»ä½ä¿¡æ¯å
容以å导è´çä»»ä½çæçº çº·ãæ³å¾äºè®®ååææ¿æ
ä»»ä½è´£ä»»ï¼å
¨é¨è´£ä»»ç±æ¨èªè¡æ¿æ
ã |
| | | 4. BladeXå¢éå¯è½ä¼ç»å¸¸æä¾äº§åæ´æ°æå级ï¼ä½BladeXå¢é没æä¸ºæ ¹æ®æ¬å议许å¯ç产åæä¾ç»´æ¤ææ´æ°ç责任ã |
| | | 5. BladeXå¢éå¯è½ä¼æç
§å®æ¹å¶å®çççè§å为æ¨è¿è¡ççï¼ä½BladeXå¢é没æä¸ºæ ¹æ®æ¬å议许å¯ç产åæä¾ææ¯æ¯æçä¹å¡æè´£ä»»ã |
| | | |
| | | å
ã æå©åæææçä¿çï¼ |
| | | BladeXå¢éä¿çæææªå¨æ¬åè®®ä¸æç¡®æäºæ¨çæææå©ãBladeXå¢éä¿çéæ¶æ´æ°æ¬åè®®çæå©ï¼å¹¶åªéå
¬ç¤ºäºå¯¹åºäº§å项ç®çLICENSEæä»¶ï¼æ éå¾å¾æ¨çäºå
åæä¸æ éå¦è¡éç¥ï¼æ´æ°åçå
容åºäºå
¬ç¤ºå³æ¶çæãæ¨å¯ä»¥éæ¶è®¿é®äº§åå°åå¹¶æ¥é
ææ°çè®¸å¯æ¡æ¬¾ï¼å¨æ´æ°çæåæ¨ç»§ç»ä½¿ç¨æ¬äº§åå被è§ä½æ¨å·²æ¥åäºæ°çæ¡æ¬¾ã |
| | | |
| | | ä¸ã åè®®ç»æ¢ |
| | | 1. æ¨ä¸æ¦å¼å§å¤å¶ãä¸è½½ãå®è£
æè
ä½¿ç¨æ¬äº§åï¼å³è¢«è§ä¸ºå®å
¨ç解并æ¥åæ¬åè®®çåé¡¹æ¡æ¬¾ï¼å¨äº«æä¸è¿°æ¡æ¬¾æäºçè®¸å¯æååæ¶ï¼ä¹åå°ç¸å
³ç约æåéå¶ï¼æ¬å议许å¯èå´ä»¥å¤çè¡ä¸ºï¼å°ç´æ¥è¿åæ¬å议并ææä¾µæã |
| | | 2. 䏿¦æ¨è¿åæ¬åè®®çæ¡æ¬¾ï¼BladeXå¢ééæ¶å¯è½ç»æ¢æ¬åè®®ãæ¶å许å¯åææï¼å¹¶è¦æ±æ¨æ¿æ
ç¸åºæ³å¾åç»æµè´£ä»»ã |
¶Ô±ÈÐÂÎļþ |
| | |
| | | ## çæå£°æ |
| | | * BladeXæ¯ä¸ä¸ªåä¸å软件ï¼ç³»å产åç¥è¯äº§æå½**䏿µ·å¸é·å¾·ç§ææéå
¬å¸**ç¬ç«ææ |
| | | * æ¨ä¸æ¦å¼å§å¤å¶ãä¸è½½ãå®è£
æè
ä½¿ç¨æ¬äº§åï¼å³è¢«è§ä¸ºå®å
¨ç解并æ¥åæ¬åè®®çåé¡¹æ¡æ¬¾ |
| | | * æ´å¤è¯¦æ
请çï¼[BladeXå䏿æè®¸å¯åè®®](/LICENSE) |
| | | |
| | | ## ççæµç¨ |
| | | >1. éå°é®é¢æBug |
| | | >2. ä¸å¡åé®é¢ææç¹è°è¯å°è¯æ¾åºé®é¢æå¨ |
| | | >3. ç³»ç»åé®é¢éè¿ç¾åº¦ãè°·æãç¤¾åºæ¥æ¾è§£å³æ¹æ¡ |
| | | >4. æªè§£å³é®é¢åè¿å
¥ææ¯ç¤¾åºè¿è¡å叿é®ï¼[https://sns.bladex.vip/](https://sns.bladex.vip/) |
| | | >5. å°å¸åå°ååè³åä¸ç¾¤ï¼ç¹å«ç®åä¸è¨ä¸¤è¯å°±è½æè¿°æ¸
æ¥çä¹å¯å¨ççæ¶é´å
åè³åä¸ç¾¤æé® |
| | | >6. åå¸çæ¶åä¸å®è¦æè¿°æ¸
æ¥ï¼è¯¦ç»æè¿°éå°é®é¢ç**éç°æ¥éª¤**ã**æ¥é详ç»ä¿¡æ¯**ã**ç¸å
³ä»£ç ä¸é»è¾**ã**使ç¨è½¯ä»¶çæ¬**以å**æä½ç³»ç»çæ¬**ï¼å¦åéæå叿é®å°ä¼æé«æä»¬çççé¾åº¦ã |
| | | |
| | | ## ççæ¶é´ |
| | | * 工使¥ï¼9:00 ~ 17:00 æä¾ççï¼å¨æ«ãè忥伿¯ï¼æåçç |
| | | * 请å¿**ç§èæé®**ï¼ä»¥å
被å
¶ä»ç¨æ·çæ¶æ¯è¦çä»èæ æ³è·å¾çç |
| | | * ççæ¶é´å¤éå°é®é¢å¯ä»¥å°é®é¢åå¸è³[ææ¯ç¤¾åº](https://sns.bladex.vip/)ï¼æä»¬åç»ä¼é个åå¤ |
| | | |
| | | ## ææèå´ |
| | | * ä¸ä¸çï¼åªå¯ç¨äº**个人å¦ä¹ **å**ä¸ªäººç§æ´»**项ç®ï¼ä¸å¯ç¨äºå
¬å¸æå¢éï¼ä¸å¯æ³é²ç»ä»»ä½ç¬¬ä¸æ¹ |
| | | * ä¼ä¸çï¼å¯ç¨äº**ä¼ä¸åä¸**çä»»ä½é¡¹ç®ï¼ä¼ä¸çåå·¥å¨**æªè´ä¹°**ä¸ä¸çææåï¼åªææå¼å**æå¨ææä¼ä¸åä¸**ç项ç®ï¼**ä¸å¾å°BladeXç¨äºä¸ªäººç§æ´»** |
| | | * å
±åéµå®ï¼è¥ç²æ¹éè¦æ¨æä¾é¡¹ç®æºç ï¼åéä»£ä¸ºç²æ¹è´ä¹°BladeXä¼ä¸ææï¼ç²æ¹è´ä¹°åç»çææé¡¹ç®é½æ é忬¡è´ä¹°ææ |
| | | |
| | | ## åç¨æç |
| | | * âï¸ éµå®[åä¸åè®®](/LICENSE)çåæä¸ï¼å°BladeXç³»å产åç¨äºææèå´å
çåç¨é¡¹ç®ï¼å¹¶ä¸çº¿è¿è¥ |
| | | * âï¸ éµå®[åä¸åè®®](/LICENSE)çåæä¸ï¼ä¸éå¶é¡¹ç®æ°ï¼ä¸éå¶æå¡å¨æ° |
| | | * âï¸ éµå®[åä¸åè®®](/LICENSE)çåæä¸ï¼å°èªè¡ç¼åçä¸å¡ä»£ç ç³è¯·è½¯ä»¶è使 |
| | | |
| | | ## ä½ä¸ºä¾µæ |
| | | * â ä¸éµå®åä¸åè®®ï¼ç§èªéå®å䏿ºç |
| | | * â 以任ä½çç±å°BladeXæºç ç¨äºç³è¯·è½¯ä»¶è使 |
| | | * â å°å䏿ºç 以任ä½éå¾ä»»ä½çç±æ³é²ç»æªææçåä½æä¸ªäºº |
| | | * â å¼å宿¯é¡¹ç®ï¼æ²¡æä¸ºç²æ¹è´ä¹°ä¼ä¸ææï¼åç²æ¹æä¾äºBladeX代ç |
| | | * â åºäºBladeXæå±ç åä¸BladeXæç«äºå
³ç³»çè¡çæ¡æ¶ï¼å¹¶å°å
¶å¼æºæéå® |
| | | |
| | | ## ä¾µæåæ |
| | | * æ
èè¾è½»ï¼ç¬¬ä¸æ¬¡åç°è¦åå¤ç |
| | | * æ
èè¾éï¼å°ç¦è´¦å·ï¼è¸¢åºåä¸ç¾¤ï¼å¹¶ä¿ç追究æ³å¾è´£ä»»çæå© |
| | | * æ
è严éï¼ä¸æ¬å°å¾å¸äºå¡æåä½ï¼ä»¥å
¬å¸åä¹èµ·è¯ä¾µç¯è®¡ç®æºè½¯ä»¶è使 |
| | | |
| | | ## ä¸¾æ¥æå¥ |
| | | * å宿¹æä¾æç¨çº¿ç´¢å¹¶æåæ£æ¯çç个人æçªç¹ï¼å°ä¼çææç»äº 500ï½10000 ä¸ççç°éå¥å± |
| | | * 宿¹å¯ä¸æå®QQï¼1272154962 |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://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.7.1</version> |
| | | <relativePath /> |
| | | </parent> |
| | | |
| | | <groupId>org.springblade.platform</groupId> |
| | | <artifactId>blade-bom</artifactId> |
| | | <packaging>pom</packaging> |
| | | <version>${bladex.tool.version}</version> |
| | | <description>bladexç»ä¸çæ¬é
ç½®</description> |
| | | |
| | | <properties> |
| | | <bladex.tool.version>3.0.1.RELEASE</bladex.tool.version> |
| | | |
| | | <swagger.version>2.10.5</swagger.version> |
| | | <swagger.models.version>1.6.2</swagger.models.version> |
| | | <knife4j.version>2.0.9</knife4j.version> |
| | | <mybatis.plus.version>3.5.2</mybatis.plus.version> |
| | | <mybatis.plus.generator.version>3.5.3</mybatis.plus.generator.version> |
| | | <mybatis.plus.dynamic.version>3.3.6</mybatis.plus.dynamic.version> |
| | | <protostuff.version>1.6.0</protostuff.version> |
| | | <disruptor.version>3.4.2</disruptor.version> |
| | | <logstash.version>6.2</logstash.version> |
| | | <druid.version>1.2.8</druid.version> |
| | | <jackson.version>2.13.3</jackson.version> |
| | | <okhttp.version>4.9.3</okhttp.version> |
| | | <xxl.job.version>2.1.2</xxl.job.version> |
| | | <log4j2.version>2.18.0</log4j2.version> |
| | | <logback.version>1.2.11</logback.version> |
| | | |
| | | <mysql.connector.version>8.0.22</mysql.connector.version> |
| | | <oracle.connector.version>12.2.0.1</oracle.connector.version> |
| | | <postgresql.connector.version>42.2.22</postgresql.connector.version> |
| | | <sqlserver.connector.version>8.4.1.jre8</sqlserver.connector.version> |
| | | <dameng.connector.version>8.1.2.141</dameng.connector.version> |
| | | |
| | | <spring.boot.admin.version>2.7.1</spring.boot.admin.version> |
| | | <alibaba.cloud.version>2021.0.1.0</alibaba.cloud.version> |
| | | <alibaba.seata.version>1.5.2</alibaba.seata.version> |
| | | <alibaba.nacos.version>2.1.0</alibaba.nacos.version> |
| | | </properties> |
| | | |
| | | <dependencyManagement> |
| | | <dependencies> |
| | | <!-- Blade --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-boot</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-cloud</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-context</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-db</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-launch</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-log4j2</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-secure</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-test</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-tool</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-actuate</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-api-crypto</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-auth</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-cache</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-datascope</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-develop</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-ehcache</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-excel</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-flowable</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-http</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-jwt</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-log</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-metrics</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-mongo</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-mybatis</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-oss</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-prometheus</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-redis</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-report</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-loadbalancer</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-sms</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-social</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-swagger</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-tenant</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-trace</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-transaction</artifactId> |
| | | <version>${bladex.tool.version}</version> |
| | | </dependency> |
| | | <!-- Nacos --> |
| | | <dependency> |
| | | <groupId>com.alibaba.cloud</groupId> |
| | | <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> |
| | | <version>${alibaba.cloud.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.alibaba.cloud</groupId> |
| | | <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> |
| | | <version>${alibaba.cloud.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.alibaba.nacos</groupId> |
| | | <artifactId>nacos-client</artifactId> |
| | | <version>${alibaba.nacos.version}</version> |
| | | </dependency> |
| | | <!-- Sentinel --> |
| | | <dependency> |
| | | <groupId>com.alibaba.cloud</groupId> |
| | | <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> |
| | | <version>${alibaba.cloud.version}</version> |
| | | </dependency> |
| | | <!-- Seata--> |
| | | <dependency> |
| | | <groupId>com.alibaba.cloud</groupId> |
| | | <artifactId>spring-cloud-starter-alibaba-seata</artifactId> |
| | | <version>${alibaba.cloud.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.seata</groupId> |
| | | <artifactId>seata-spring-boot-starter</artifactId> |
| | | <version>${alibaba.seata.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.seata</groupId> |
| | | <artifactId>seata-all</artifactId> |
| | | <version>${alibaba.seata.version}</version> |
| | | </dependency> |
| | | <!--Mybatis--> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus</artifactId> |
| | | <version>${mybatis.plus.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-boot-starter</artifactId> |
| | | <version>${mybatis.plus.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-extension</artifactId> |
| | | <version>${mybatis.plus.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-generator</artifactId> |
| | | <version>${mybatis.plus.generator.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>dynamic-datasource-spring-boot-starter</artifactId> |
| | | <version>${mybatis.plus.dynamic.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.mybatis</groupId> |
| | | <artifactId>mybatis-typehandlers-jsr310</artifactId> |
| | | <version>1.0.2</version> |
| | | </dependency> |
| | | <!-- JWT --> |
| | | <dependency> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt-impl</artifactId> |
| | | <version>0.11.2</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt-jackson</artifactId> |
| | | <version>0.11.2</version> |
| | | </dependency> |
| | | <!-- Admin --> |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-server</artifactId> |
| | | <version>${spring.boot.admin.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-client</artifactId> |
| | | <version>${spring.boot.admin.version}</version> |
| | | </dependency> |
| | | <!-- Druid --> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>druid</artifactId> |
| | | <version>${druid.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>druid-spring-boot-starter</artifactId> |
| | | <version>${druid.version}</version> |
| | | </dependency> |
| | | <!-- MySql --> |
| | | <dependency> |
| | | <groupId>mysql</groupId> |
| | | <artifactId>mysql-connector-java</artifactId> |
| | | <version>${mysql.connector.version}</version> |
| | | </dependency> |
| | | <!-- Oracle --> |
| | | <dependency> |
| | | <groupId>com.oracle</groupId> |
| | | <artifactId>ojdbc7</artifactId> |
| | | <version>${oracle.connector.version}</version> |
| | | </dependency> |
| | | <!-- PostgreSql --> |
| | | <dependency> |
| | | <groupId>org.postgresql</groupId> |
| | | <artifactId>postgresql</artifactId> |
| | | <version>${postgresql.connector.version}</version> |
| | | </dependency> |
| | | <!-- SqlServer --> |
| | | <dependency> |
| | | <groupId>com.microsoft.sqlserver</groupId> |
| | | <artifactId>mssql-jdbc</artifactId> |
| | | <version>${sqlserver.connector.version}</version> |
| | | </dependency> |
| | | <!-- DaMeng --> |
| | | <dependency> |
| | | <groupId>com.dameng</groupId> |
| | | <artifactId>DmJdbcDriver18</artifactId> |
| | | <version>${dameng.connector.version}</version> |
| | | </dependency> |
| | | <!--Swagger--> |
| | | <dependency> |
| | | <groupId>io.springfox</groupId> |
| | | <artifactId>springfox-swagger2</artifactId> |
| | | <version>${swagger.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.swagger</groupId> |
| | | <artifactId>swagger-models</artifactId> |
| | | <version>${swagger.models.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.github.xiaoymin</groupId> |
| | | <artifactId>knife4j-micro-spring-boot-starter</artifactId> |
| | | <version>${knife4j.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.github.xiaoymin</groupId> |
| | | <artifactId>knife4j-aggregation-spring-boot-starter</artifactId> |
| | | <version>${knife4j.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.github.xiaoymin</groupId> |
| | | <artifactId>knife4j-spring-ui</artifactId> |
| | | <version>${knife4j.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.plugin</groupId> |
| | | <artifactId>spring-plugin-core</artifactId> |
| | | <version>2.0.0.RELEASE</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.plugin</groupId> |
| | | <artifactId>spring-plugin-metadata</artifactId> |
| | | <version>2.0.0.RELEASE</version> |
| | | </dependency> |
| | | <!-- protostuff --> |
| | | <dependency> |
| | | <groupId>io.protostuff</groupId> |
| | | <artifactId>protostuff-core</artifactId> |
| | | <version>${protostuff.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.protostuff</groupId> |
| | | <artifactId>protostuff-runtime</artifactId> |
| | | <version>${protostuff.version}</version> |
| | | </dependency> |
| | | <!-- http --> |
| | | <dependency> |
| | | <groupId>org.jsoup</groupId> |
| | | <artifactId>jsoup</artifactId> |
| | | <version>1.12.1</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.squareup.okhttp3</groupId> |
| | | <artifactId>okhttp</artifactId> |
| | | <version>${okhttp.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.squareup.okhttp3</groupId> |
| | | <artifactId>logging-interceptor</artifactId> |
| | | <version>${okhttp.version}</version> |
| | | </dependency> |
| | | <!-- redisson --> |
| | | <dependency> |
| | | <groupId>org.redisson</groupId> |
| | | <artifactId>redisson</artifactId> |
| | | <version>3.11.6</version> |
| | | </dependency> |
| | | <!-- Disruptor --> |
| | | <dependency> |
| | | <groupId>com.lmax</groupId> |
| | | <artifactId>disruptor</artifactId> |
| | | <version>${disruptor.version}</version> |
| | | </dependency> |
| | | <!-- Logstash --> |
| | | <dependency> |
| | | <groupId>net.logstash.logback</groupId> |
| | | <artifactId>logstash-logback-encoder</artifactId> |
| | | <version>${logstash.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.codehaus.janino</groupId> |
| | | <artifactId>janino</artifactId> |
| | | <version>3.0.15</version> |
| | | </dependency> |
| | | <!-- xxljob --> |
| | | <dependency> |
| | | <groupId>com.xuxueli</groupId> |
| | | <artifactId>xxl-job-core</artifactId> |
| | | <version>${xxl.job.version}</version> |
| | | </dependency> |
| | | <!-- captcha --> |
| | | <dependency> |
| | | <groupId>com.github.whvcse</groupId> |
| | | <artifactId>easy-captcha</artifactId> |
| | | <version>1.6.2</version> |
| | | </dependency> |
| | | <!-- jackson --> |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.module</groupId> |
| | | <artifactId>jackson-module-jaxb-annotations</artifactId> |
| | | <version>${jackson.version}</version> |
| | | </dependency> |
| | | <!-- fastjson --> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>fastjson</artifactId> |
| | | <version>1.2.83_noneautotype</version> |
| | | </dependency> |
| | | <!-- sentinel --> |
| | | <dependency> |
| | | <groupId>com.alibaba.csp</groupId> |
| | | <artifactId>sentinel-core</artifactId> |
| | | <version>1.8.4</version> |
| | | </dependency> |
| | | <!-- easyexcel --> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>easyexcel</artifactId> |
| | | <version>2.2.11</version> |
| | | </dependency> |
| | | <!-- JustAuth --> |
| | | <dependency> |
| | | <groupId>me.zhyd.oauth</groupId> |
| | | <artifactId>JustAuth</artifactId> |
| | | <version>1.16.5</version> |
| | | </dependency> |
| | | <!-- Guava --> |
| | | <dependency> |
| | | <groupId>com.google.guava</groupId> |
| | | <artifactId>guava</artifactId> |
| | | <version>30.1.1-jre</version> |
| | | </dependency> |
| | | <!-- Prometheus --> |
| | | <dependency> |
| | | <groupId>io.micrometer</groupId> |
| | | <artifactId>micrometer-core</artifactId> |
| | | <version>1.9.1</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.micrometer</groupId> |
| | | <artifactId>micrometer-registry-prometheus</artifactId> |
| | | <version>1.9.1</version> |
| | | </dependency> |
| | | <!--AliOss--> |
| | | <dependency> |
| | | <groupId>com.aliyun.oss</groupId> |
| | | <artifactId>aliyun-sdk-oss</artifactId> |
| | | <version>3.14.0</version> |
| | | </dependency> |
| | | <!--MinIO--> |
| | | <dependency> |
| | | <groupId>io.minio</groupId> |
| | | <artifactId>minio</artifactId> |
| | | <version>8.3.7</version> |
| | | </dependency> |
| | | <!--QiNiu--> |
| | | <dependency> |
| | | <groupId>com.qiniu</groupId> |
| | | <artifactId>qiniu-java-sdk</artifactId> |
| | | <version>7.9.4</version> |
| | | </dependency> |
| | | <!--è
¾è®¯COS--> |
| | | <dependency> |
| | | <groupId>com.qcloud</groupId> |
| | | <artifactId>cos_api</artifactId> |
| | | <version>5.6.69</version> |
| | | </dependency> |
| | | <!--å为äºObs--> |
| | | <dependency> |
| | | <groupId>com.huaweicloud</groupId> |
| | | <artifactId>esdk-obs-java</artifactId> |
| | | <version>3.21.12</version> |
| | | </dependency> |
| | | <!--AliSms--> |
| | | <dependency> |
| | | <groupId>com.aliyun</groupId> |
| | | <artifactId>aliyun-java-sdk-core</artifactId> |
| | | <version>4.5.30</version> |
| | | </dependency> |
| | | <!--YunPian--> |
| | | <dependency> |
| | | <groupId>com.yunpian.sdk</groupId> |
| | | <artifactId>yunpian-java-sdk</artifactId> |
| | | <version>1.2.7</version> |
| | | </dependency> |
| | | <!--è
¾è®¯SMS--> |
| | | <dependency> |
| | | <groupId>com.github.qcloudsms</groupId> |
| | | <artifactId>qcloudsms</artifactId> |
| | | <version>1.0.6</version> |
| | | </dependency> |
| | | <!-- oauth2 --> |
| | | <dependency> |
| | | <groupId>org.springframework.security.oauth</groupId> |
| | | <artifactId>spring-security-oauth2</artifactId> |
| | | <version>2.3.8.RELEASE</version> |
| | | </dependency> |
| | | <!-- findbugs --> |
| | | <dependency> |
| | | <groupId>com.google.code.findbugs</groupId> |
| | | <artifactId>jsr305</artifactId> |
| | | <version>3.0.2</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | <version>1.18.22</version> |
| | | </dependency> |
| | | <!-- log4j2 --> |
| | | <dependency> |
| | | <groupId>org.apache.logging.log4j</groupId> |
| | | <artifactId>log4j-api</artifactId> |
| | | <version>${log4j2.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.logging.log4j</groupId> |
| | | <artifactId>log4j-core</artifactId> |
| | | <version>${log4j2.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.logging.log4j</groupId> |
| | | <artifactId>log4j-jul</artifactId> |
| | | <version>${log4j2.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.logging.log4j</groupId> |
| | | <artifactId>log4j-slf4j-impl</artifactId> |
| | | <version>${log4j2.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.logging.log4j</groupId> |
| | | <artifactId>log4j-to-slf4j</artifactId> |
| | | <version>${log4j2.version}</version> |
| | | </dependency> |
| | | <!-- logback --> |
| | | <dependency> |
| | | <groupId>ch.qos.logback</groupId> |
| | | <artifactId>logback-classic</artifactId> |
| | | <version>${logback.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>ch.qos.logback</groupId> |
| | | <artifactId>logback-core</artifactId> |
| | | <version>${logback.version}</version> |
| | | </dependency> |
| | | </dependencies> |
| | | </dependencyManagement> |
| | | |
| | | <distributionManagement> |
| | | <repository> |
| | | <id>blade-release</id> |
| | | <name>Release Repository</name> |
| | | <url>http://nexus.javablade.com/repository/maven-releases/</url> |
| | | </repository> |
| | | </distributionManagement> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | # auto 代ç èªå¨çæ |
| | | |
| | | ## è§å |
| | | 1. çæ java spi |
| | | 2. ç¨æ¥çæ `spring.factories` |
| | | 3. èèçæ `spring-devtools.properties` |
| | | 4. èèï¼çæ `swagger` 注解 |
| | | |
| | | ## åè |
| | | Google Auto: https://github.com/google/auto |
| | | |
| | | Spring 5 - spring-context-indexerï¼https://github.com/spring-projects/spring-framework/tree/master/spring-context-indexer |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | |
| | | <parent> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <groupId>org.springblade</groupId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-compiler-plugin</artifactId> |
| | | <version>${maven.plugin.version}</version> |
| | | <configuration> |
| | | <annotationProcessorPaths> |
| | | <path> |
| | | <groupId>org.hibernate.validator</groupId> |
| | | <artifactId>hibernate-validator-annotation-processor</artifactId> |
| | | <version>6.0.13.Final</version> |
| | | </path> |
| | | </annotationProcessorPaths> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.annotation; |
| | | |
| | | import java.lang.annotation.Documented; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.Target; |
| | | |
| | | import static java.lang.annotation.ElementType.TYPE; |
| | | import static java.lang.annotation.RetentionPolicy.SOURCE; |
| | | |
| | | /** |
| | | * ApplicationContextInitializer å¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Documented |
| | | @Retention(SOURCE) |
| | | @Target(TYPE) |
| | | public @interface AutoContextInitializer { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.annotation; |
| | | |
| | | import java.lang.annotation.Documented; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.Target; |
| | | |
| | | import static java.lang.annotation.ElementType.TYPE; |
| | | import static java.lang.annotation.RetentionPolicy.SOURCE; |
| | | |
| | | /** |
| | | * EnvironmentPostProcessor å¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Documented |
| | | @Retention(SOURCE) |
| | | @Target(TYPE) |
| | | public @interface AutoEnvPostProcessor { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.annotation; |
| | | |
| | | import java.lang.annotation.Documented; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.Target; |
| | | |
| | | import static java.lang.annotation.ElementType.TYPE; |
| | | import static java.lang.annotation.RetentionPolicy.SOURCE; |
| | | |
| | | /** |
| | | * FailureAnalyzer å¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Documented |
| | | @Retention(SOURCE) |
| | | @Target(TYPE) |
| | | public @interface AutoFailureAnalyzer { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.annotation; |
| | | |
| | | import java.lang.annotation.Documented; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.Target; |
| | | |
| | | import static java.lang.annotation.ElementType.TYPE; |
| | | import static java.lang.annotation.RetentionPolicy.SOURCE; |
| | | |
| | | /** |
| | | * AutoIgnore å¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Documented |
| | | @Retention(SOURCE) |
| | | @Target(TYPE) |
| | | public @interface AutoIgnore { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.annotation; |
| | | |
| | | import java.lang.annotation.Documented; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.Target; |
| | | |
| | | import static java.lang.annotation.ElementType.TYPE; |
| | | import static java.lang.annotation.RetentionPolicy.SOURCE; |
| | | |
| | | /** |
| | | * ApplicationListener å¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Documented |
| | | @Retention(SOURCE) |
| | | @Target(TYPE) |
| | | public @interface AutoListener { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.annotation; |
| | | |
| | | import java.lang.annotation.Documented; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.Target; |
| | | |
| | | import static java.lang.annotation.ElementType.TYPE; |
| | | import static java.lang.annotation.RetentionPolicy.SOURCE; |
| | | |
| | | /** |
| | | * SpringApplicationRunListener å¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Documented |
| | | @Retention(SOURCE) |
| | | @Target(TYPE) |
| | | public @interface AutoRunListener { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.common; |
| | | |
| | | import javax.annotation.processing.AbstractProcessor; |
| | | import javax.annotation.processing.RoundEnvironment; |
| | | import javax.lang.model.SourceVersion; |
| | | import javax.lang.model.element.AnnotationMirror; |
| | | import javax.lang.model.element.Element; |
| | | import javax.lang.model.element.TypeElement; |
| | | import javax.tools.Diagnostic.Kind; |
| | | import java.io.PrintWriter; |
| | | import java.io.StringWriter; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * æ½è±¡ å¤çå¨ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public abstract class AbstractBladeProcessor extends AbstractProcessor { |
| | | |
| | | @Override |
| | | public SourceVersion getSupportedSourceVersion() { |
| | | return SourceVersion.latestSupported(); |
| | | } |
| | | |
| | | /** |
| | | * AutoService 注解å¤çå¨ |
| | | * @param annotations 注解 getSupportedAnnotationTypes |
| | | * @param roundEnv æ«æå°ç æ³¨è§£æ° |
| | | * @return æ¯å¦å®æ |
| | | */ |
| | | @Override |
| | | public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
| | | try { |
| | | return processImpl(annotations, roundEnv); |
| | | } catch (Exception e) { |
| | | fatalError(e); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | protected abstract boolean processImpl(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv); |
| | | |
| | | protected void log(String msg) { |
| | | if (processingEnv.getOptions().containsKey("debug")) { |
| | | processingEnv.getMessager().printMessage(Kind.NOTE, msg); |
| | | } |
| | | } |
| | | |
| | | protected void error(String msg, Element element, AnnotationMirror annotation) { |
| | | processingEnv.getMessager().printMessage(Kind.ERROR, msg, element, annotation); |
| | | } |
| | | |
| | | protected void fatalError(Exception e) { |
| | | // We don't allow exceptions of any kind to propagate to the compiler |
| | | StringWriter writer = new StringWriter(); |
| | | e.printStackTrace(new PrintWriter(writer)); |
| | | fatalError(writer.toString()); |
| | | } |
| | | |
| | | protected void fatalError(String msg) { |
| | | processingEnv.getMessager().printMessage(Kind.ERROR, "FATAL ERROR: " + msg); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.common; |
| | | |
| | | import org.springblade.core.auto.annotation.*; |
| | | |
| | | /** |
| | | * 注解类å |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public enum BootAutoType { |
| | | /** |
| | | * Componentï¼ç»åæ³¨è§£ï¼æ·»å å° spring.factories |
| | | */ |
| | | COMPONENT("org.springframework.stereotype.Component", "org.springframework.boot.autoconfigure.EnableAutoConfiguration"), |
| | | /** |
| | | * ApplicationContextInitializer æ·»å å° spring.factories |
| | | */ |
| | | CONTEXT_INITIALIZER(AutoContextInitializer.class.getName(), "org.springframework.context.ApplicationContextInitializer"), |
| | | /** |
| | | * ApplicationListener æ·»å å° spring.factories |
| | | */ |
| | | LISTENER(AutoListener.class.getName(), "org.springframework.context.ApplicationListener"), |
| | | /** |
| | | * SpringApplicationRunListener æ·»å å° spring.factories |
| | | */ |
| | | RUN_LISTENER(AutoRunListener.class.getName(), "org.springframework.boot.SpringApplicationRunListener"), |
| | | /** |
| | | * FailureAnalyzer æ·»å å° spring.factories |
| | | */ |
| | | FAILURE_ANALYZER(AutoFailureAnalyzer.class.getName(), "org.springframework.boot.diagnostics.FailureAnalyzer"), |
| | | /** |
| | | * EnvironmentPostProcessor æ·»å å° spring.factories |
| | | */ |
| | | ENV_POST_PROCESSOR(AutoEnvPostProcessor.class.getName(), "org.springframework.boot.env.EnvironmentPostProcessor"); |
| | | |
| | | private final String annotationName; |
| | | private final String configureKey; |
| | | |
| | | BootAutoType(String annotationName, String configureKey) { |
| | | this.annotationName = annotationName; |
| | | this.configureKey = configureKey; |
| | | } |
| | | |
| | | public final String getAnnotationName() { |
| | | return annotationName; |
| | | } |
| | | |
| | | public final String getConfigureKey() { |
| | | return configureKey; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.common; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * MultiSetMap |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class MultiSetMap<K, V> { |
| | | private transient final Map<K, Set<V>> map; |
| | | |
| | | public MultiSetMap() { |
| | | map = new HashMap<>(); |
| | | } |
| | | |
| | | private Set<V> createSet() { |
| | | return new HashSet<>(); |
| | | } |
| | | |
| | | /** |
| | | * put to MultiSetMap |
| | | * |
| | | * @param key é® |
| | | * @param value å¼ |
| | | * @return boolean |
| | | */ |
| | | public boolean put(K key, V value) { |
| | | Set<V> set = map.get(key); |
| | | if (set == null) { |
| | | set = createSet(); |
| | | if (set.add(value)) { |
| | | map.put(key, set); |
| | | return true; |
| | | } else { |
| | | throw new AssertionError("New set violated the set spec"); |
| | | } |
| | | } else if (set.add(value)) { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦å
å«æä¸ªkey |
| | | * |
| | | * @param key key |
| | | * @return ç»æ |
| | | */ |
| | | public boolean containsKey(K key) { |
| | | return map.containsKey(key); |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦å
å« value ä¸çæä¸ªå¼ |
| | | * |
| | | * @param value value |
| | | * @return æ¯å¦å
å« |
| | | */ |
| | | public boolean containsVal(V value) { |
| | | Collection<Set<V>> values = map.values(); |
| | | return values.stream().anyMatch(vs -> vs.contains(value)); |
| | | } |
| | | |
| | | /** |
| | | * key éå |
| | | * |
| | | * @return keys |
| | | */ |
| | | public Set<K> keySet() { |
| | | return map.keySet(); |
| | | } |
| | | |
| | | /** |
| | | * put list to MultiSetMap |
| | | * |
| | | * @param key é® |
| | | * @param set å¼å表 |
| | | * @return boolean |
| | | */ |
| | | public boolean putAll(K key, Set<V> set) { |
| | | if (set == null) { |
| | | return false; |
| | | } else { |
| | | map.put(key, set); |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * get List by key |
| | | * |
| | | * @param key é® |
| | | * @return List |
| | | */ |
| | | public Set<V> get(K key) { |
| | | return map.get(key); |
| | | } |
| | | |
| | | /** |
| | | * clear MultiSetMap |
| | | */ |
| | | public void clear() { |
| | | map.clear(); |
| | | } |
| | | |
| | | /** |
| | | * isEmpty |
| | | * |
| | | * @return isEmpty |
| | | */ |
| | | public boolean isEmpty() { |
| | | return map.isEmpty(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.common; |
| | | |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | import java.util.stream.Stream; |
| | | |
| | | /** |
| | | * éå å·¥å
·ç±» |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class Sets { |
| | | |
| | | /** |
| | | * ä¸å¯å éå |
| | | * |
| | | * @param es 对象 |
| | | * @param <E> æ³å |
| | | * @return éå |
| | | */ |
| | | @SafeVarargs |
| | | public static <E> Set<E> ofImmutableSet(E... es) { |
| | | Objects.requireNonNull(es); |
| | | return Stream.of(es).collect(Collectors.toSet()); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.common; |
| | | |
| | | import javax.annotation.processing.ProcessingEnvironment; |
| | | import javax.lang.model.element.AnnotationMirror; |
| | | import javax.lang.model.element.Element; |
| | | import javax.lang.model.element.QualifiedNameable; |
| | | import javax.lang.model.element.TypeElement; |
| | | import javax.lang.model.type.DeclaredType; |
| | | import javax.lang.model.type.TypeMirror; |
| | | import javax.lang.model.util.Types; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Type utilities. |
| | | * |
| | | * @author Stephane Nicoll |
| | | * @since 5.0 |
| | | */ |
| | | public class TypeHelper { |
| | | |
| | | private final ProcessingEnvironment env; |
| | | |
| | | private final Types types; |
| | | |
| | | |
| | | public TypeHelper(ProcessingEnvironment env) { |
| | | this.env = env; |
| | | this.types = env.getTypeUtils(); |
| | | } |
| | | |
| | | |
| | | public String getType(Element element) { |
| | | return getType(element != null ? element.asType() : null); |
| | | } |
| | | |
| | | public String getType(AnnotationMirror annotation) { |
| | | return getType(annotation != null ? annotation.getAnnotationType() : null); |
| | | } |
| | | |
| | | public String getType(TypeMirror type) { |
| | | if (type == null) { |
| | | return null; |
| | | } |
| | | if (type instanceof DeclaredType) { |
| | | DeclaredType declaredType = (DeclaredType) type; |
| | | Element enclosingElement = declaredType.asElement().getEnclosingElement(); |
| | | if (enclosingElement != null && enclosingElement instanceof TypeElement) { |
| | | return getQualifiedName(enclosingElement) + "$" + declaredType.asElement().getSimpleName().toString(); |
| | | } else { |
| | | return getQualifiedName(declaredType.asElement()); |
| | | } |
| | | } |
| | | return type.toString(); |
| | | } |
| | | |
| | | private String getQualifiedName(Element element) { |
| | | if (element instanceof QualifiedNameable) { |
| | | return ((QualifiedNameable) element).getQualifiedName().toString(); |
| | | } |
| | | return element.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Return the super class of the specified {@link Element} or null if this |
| | | * {@code element} represents {@link Object}. |
| | | * |
| | | * @param element Element |
| | | * @return Element |
| | | */ |
| | | public Element getSuperClass(Element element) { |
| | | List<? extends TypeMirror> superTypes = this.types.directSupertypes(element.asType()); |
| | | if (superTypes.isEmpty()) { |
| | | // reached java.lang.Object |
| | | return null; |
| | | } |
| | | return this.types.asElement(superTypes.get(0)); |
| | | } |
| | | |
| | | /** |
| | | * Return the interfaces that are <strong>directly</strong> implemented by the |
| | | * specified {@link Element} or an empty list if this {@code element} does not |
| | | * implement any interface. |
| | | * |
| | | * @param element Element |
| | | * @return Element list |
| | | */ |
| | | public List<Element> getDirectInterfaces(Element element) { |
| | | List<? extends TypeMirror> superTypes = this.types.directSupertypes(element.asType()); |
| | | List<Element> directInterfaces = new ArrayList<>(); |
| | | // index 0 is the super class |
| | | if (superTypes.size() > 1) { |
| | | for (int i = 1; i < superTypes.size(); i++) { |
| | | Element e = this.types.asElement(superTypes.get(i)); |
| | | if (e != null) { |
| | | directInterfaces.add(e); |
| | | } |
| | | } |
| | | } |
| | | return directInterfaces; |
| | | } |
| | | |
| | | public List<? extends AnnotationMirror> getAllAnnotationMirrors(Element e) { |
| | | return this.env.getElementUtils().getAllAnnotationMirrors(e); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.factories; |
| | | |
| | | import org.springblade.core.auto.annotation.AutoIgnore; |
| | | import org.springblade.core.auto.common.AbstractBladeProcessor; |
| | | import org.springblade.core.auto.common.BootAutoType; |
| | | import org.springblade.core.auto.common.MultiSetMap; |
| | | import org.springblade.core.auto.service.AutoService; |
| | | |
| | | import javax.annotation.processing.*; |
| | | import javax.lang.model.element.AnnotationMirror; |
| | | import javax.lang.model.element.Element; |
| | | import javax.lang.model.element.ElementKind; |
| | | import javax.lang.model.element.TypeElement; |
| | | import javax.lang.model.util.Elements; |
| | | import javax.tools.FileObject; |
| | | import javax.tools.StandardLocation; |
| | | import java.io.IOException; |
| | | import java.net.URI; |
| | | import java.net.URISyntaxException; |
| | | import java.nio.file.Path; |
| | | import java.nio.file.Paths; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * spring boot èªå¨é
ç½®å¤çå¨ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoService(Processor.class) |
| | | @SupportedAnnotationTypes("*") |
| | | @SupportedOptions("debug") |
| | | public class AutoFactoriesProcessor extends AbstractBladeProcessor { |
| | | /** |
| | | * å¤ççæ³¨è§£ @FeignClient |
| | | */ |
| | | private static final String FEIGN_CLIENT_ANNOTATION = "org.springframework.cloud.openfeign.FeignClient"; |
| | | /** |
| | | * Feign èªå¨é
ç½® |
| | | */ |
| | | private static final String FEIGN_AUTO_CONFIGURE_KEY = "org.springblade.core.cloud.feign.BladeFeignAutoConfiguration"; |
| | | /** |
| | | * The location to look for factories. |
| | | * <p>Can be present in multiple JAR files. |
| | | */ |
| | | private static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; |
| | | /** |
| | | * devtoolsï¼æ Configuration 注解ç jar ä¸è¬éè¦ devtools é
ç½®æä»¶ |
| | | */ |
| | | private static final String DEVTOOLS_RESOURCE_LOCATION = "META-INF/spring-devtools.properties"; |
| | | /** |
| | | * æ°æ®æ¿è½½ |
| | | */ |
| | | private final MultiSetMap<String, String> factories = new MultiSetMap<>(); |
| | | /** |
| | | * å
ç´ è¾
å©ç±» |
| | | */ |
| | | private Elements elementUtils; |
| | | |
| | | @Override |
| | | public synchronized void init(ProcessingEnvironment processingEnv) { |
| | | super.init(processingEnv); |
| | | elementUtils = processingEnv.getElementUtils(); |
| | | } |
| | | |
| | | @Override |
| | | protected boolean processImpl(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
| | | if (roundEnv.processingOver()) { |
| | | generateFactoriesFiles(); |
| | | } else { |
| | | processAnnotations(annotations, roundEnv); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private void processAnnotations(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
| | | // æ¥å¿ æå°ä¿¡æ¯ gradle build --debug |
| | | log(annotations.toString()); |
| | | Set<? extends Element> elementSet = roundEnv.getRootElements(); |
| | | log("All Element set: " + elementSet.toString()); |
| | | |
| | | // è¿æ»¤ TypeElement |
| | | Set<TypeElement> typeElementSet = elementSet.stream() |
| | | .filter(this::isClassOrInterface) |
| | | .filter(e -> e instanceof TypeElement) |
| | | .map(e -> (TypeElement) e) |
| | | .collect(Collectors.toSet()); |
| | | // å¦æä¸ºç©ºç´æ¥è·³åº |
| | | if (typeElementSet.isEmpty()) { |
| | | log("Annotations elementSet is isEmpty"); |
| | | return; |
| | | } |
| | | |
| | | for (TypeElement typeElement : typeElementSet) { |
| | | if (isAnnotation(elementUtils, typeElement, AutoIgnore.class.getName())) { |
| | | log("Found @AutoIgnore annotationï¼ignore Element: " + typeElement.toString()); |
| | | } else if (isAnnotation(elementUtils, typeElement, FEIGN_CLIENT_ANNOTATION)) { |
| | | log("Found @FeignClient Element: " + typeElement.toString()); |
| | | |
| | | ElementKind elementKind = typeElement.getKind(); |
| | | // Feign Client åªå¤ç æ¥å£ |
| | | if (ElementKind.INTERFACE != elementKind) { |
| | | fatalError("@FeignClient Element " + typeElement.toString() + " 䏿¯æ¥å£ã"); |
| | | continue; |
| | | } |
| | | |
| | | String factoryName = typeElement.getQualifiedName().toString(); |
| | | if (factories.containsVal(factoryName)) { |
| | | continue; |
| | | } |
| | | |
| | | log("读åå°æ°é
ç½® spring.factories factoryNameï¼" + factoryName); |
| | | factories.put(FEIGN_AUTO_CONFIGURE_KEY, factoryName); |
| | | } else { |
| | | for (BootAutoType autoType : BootAutoType.values()) { |
| | | String annotation = autoType.getAnnotationName(); |
| | | if (isAnnotation(elementUtils, typeElement, annotation)) { |
| | | log("Found @" + annotation + " Element: " + typeElement.toString()); |
| | | |
| | | String factoryName = typeElement.getQualifiedName().toString(); |
| | | if (factories.containsVal(factoryName)) { |
| | | continue; |
| | | } |
| | | |
| | | log("读åå°æ°é
ç½® spring.factories factoryNameï¼" + factoryName); |
| | | factories.put(autoType.getConfigureKey(), factoryName); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void generateFactoriesFiles() { |
| | | if (factories.isEmpty()) { |
| | | return; |
| | | } |
| | | Filer filer = processingEnv.getFiler(); |
| | | try { |
| | | // 1. spring.factories |
| | | FileObject factoriesFile = filer.createResource(StandardLocation.CLASS_OUTPUT, "", FACTORIES_RESOURCE_LOCATION); |
| | | FactoriesFiles.writeFactoriesFile(factories, factoriesFile.openOutputStream()); |
| | | String classesPath = factoriesFile.toUri().toString().split("classes")[0]; |
| | | Path projectPath = Paths.get(new URI(classesPath)).getParent(); |
| | | // 2. devtools é
ç½®ï¼å 为æ @Configuration 注解çéè¦ devtools |
| | | String projectName = projectPath.getFileName().toString(); |
| | | FileObject devToolsFile = filer.createResource(StandardLocation.CLASS_OUTPUT, "", DEVTOOLS_RESOURCE_LOCATION); |
| | | FactoriesFiles.writeDevToolsFile(projectName, devToolsFile.openOutputStream()); |
| | | } catch (IOException | URISyntaxException e) { |
| | | fatalError(e); |
| | | } |
| | | } |
| | | |
| | | private boolean isClassOrInterface(Element e) { |
| | | ElementKind kind = e.getKind(); |
| | | return kind == ElementKind.CLASS || kind == ElementKind.INTERFACE; |
| | | } |
| | | |
| | | private boolean isAnnotation(Elements elementUtils, Element e, String annotationFullName) { |
| | | List<? extends AnnotationMirror> annotationList = elementUtils.getAllAnnotationMirrors(e); |
| | | for (AnnotationMirror annotation : annotationList) { |
| | | // 妿æ¯å¯¹äºç注解 |
| | | if (isAnnotation(annotationFullName, annotation)) { |
| | | return true; |
| | | } |
| | | // å¤çç»å注解 |
| | | Element element = annotation.getAnnotationType().asElement(); |
| | | // å¦ææ¯ java å
注解ï¼ç»§ç»å¾ªç¯ |
| | | if (element.toString().startsWith("java.lang")) { |
| | | continue; |
| | | } |
| | | // éå½å¤ç ç»å注解 |
| | | if (isAnnotation(elementUtils, element, annotationFullName)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private boolean isAnnotation(String annotationFullName, AnnotationMirror annotation) { |
| | | return annotationFullName.equals(annotation.getAnnotationType().toString()); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.factories; |
| | | |
| | | import org.springblade.core.auto.common.MultiSetMap; |
| | | |
| | | import java.io.BufferedWriter; |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | | import java.io.OutputStreamWriter; |
| | | import java.nio.charset.Charset; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.Set; |
| | | import java.util.StringJoiner; |
| | | |
| | | /** |
| | | * spring boot èªå¨åé
置工å
·ç±» |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | class FactoriesFiles { |
| | | private static final Charset UTF_8 = StandardCharsets.UTF_8; |
| | | |
| | | /** |
| | | * ååº spring.factories æä»¶ |
| | | * @param factories factories ä¿¡æ¯ |
| | | * @param output è¾åºæµ |
| | | * @throws IOException å¼å¸¸ä¿¡æ¯ |
| | | */ |
| | | static void writeFactoriesFile(MultiSetMap<String, String> factories, |
| | | OutputStream output) throws IOException { |
| | | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, UTF_8)); |
| | | Set<String> keySet = factories.keySet(); |
| | | for (String key : keySet) { |
| | | Set<String> values = factories.get(key); |
| | | if (values == null || values.isEmpty()) { |
| | | continue; |
| | | } |
| | | writer.write(key); |
| | | writer.write("=\\\n "); |
| | | StringJoiner joiner = new StringJoiner(",\\\n "); |
| | | for (String value : values) { |
| | | joiner.add(value); |
| | | } |
| | | writer.write(joiner.toString()); |
| | | writer.newLine(); |
| | | } |
| | | writer.flush(); |
| | | output.close(); |
| | | } |
| | | |
| | | /** |
| | | * ååº spring-devtools.properties |
| | | * @param projectName 项ç®å |
| | | * @param output è¾åºæµ |
| | | * @throws IOException å¼å¸¸ä¿¡æ¯ |
| | | */ |
| | | static void writeDevToolsFile(String projectName, |
| | | OutputStream output) throws IOException { |
| | | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, UTF_8)); |
| | | String format = "restart.include.%s=/%s[\\\\w-]+\\.jar"; |
| | | writer.write(String.format(format, projectName, projectName)); |
| | | writer.flush(); |
| | | output.close(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.service; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * An annotation for service providers as described in {@link java.util.ServiceLoader}. The {@link |
| | | * AutoServiceProcessor} generates the configuration files which |
| | | * allows service providers to be loaded with {@link java.util.ServiceLoader#load(Class)}. |
| | | * |
| | | * <p>Service providers assert that they conform to the service provider specification. |
| | | * Specifically, they must: |
| | | * |
| | | * <ul> |
| | | * <li>be a non-inner, non-anonymous, concrete class |
| | | * <li>have a publicly accessible no-arg constructor |
| | | * <li>implement the interface type returned by {@code value()} |
| | | * </ul> |
| | | * |
| | | * @author google |
| | | */ |
| | | @Documented |
| | | @Retention(RetentionPolicy.SOURCE) |
| | | @Target(ElementType.TYPE) |
| | | public @interface AutoService { |
| | | /** |
| | | * Returns the interfaces implemented by this service provider. |
| | | * |
| | | * @return interface array |
| | | */ |
| | | Class<?>[] value(); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.service; |
| | | |
| | | import org.springblade.core.auto.common.AbstractBladeProcessor; |
| | | import org.springblade.core.auto.common.MultiSetMap; |
| | | import org.springblade.core.auto.common.Sets; |
| | | import org.springblade.core.auto.common.TypeHelper; |
| | | |
| | | import javax.annotation.processing.Filer; |
| | | import javax.annotation.processing.ProcessingEnvironment; |
| | | import javax.annotation.processing.RoundEnvironment; |
| | | import javax.annotation.processing.SupportedOptions; |
| | | import javax.lang.model.element.*; |
| | | import javax.lang.model.type.TypeMirror; |
| | | import javax.lang.model.util.ElementFilter; |
| | | import javax.lang.model.util.Elements; |
| | | import javax.lang.model.util.SimpleAnnotationValueVisitor8; |
| | | import javax.lang.model.util.Types; |
| | | import javax.tools.FileObject; |
| | | import javax.tools.StandardLocation; |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | | import java.lang.annotation.Annotation; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * java spi æå¡èªå¨å¤çå¨ åèï¼google auto |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @SupportedOptions("debug") |
| | | public class AutoServiceProcessor extends AbstractBladeProcessor { |
| | | /** |
| | | * spi æå¡éåï¼key æ¥å£ -> value å®ç°å表 |
| | | */ |
| | | private final MultiSetMap<String, String> providers = new MultiSetMap<>(); |
| | | private TypeHelper typeHelper; |
| | | |
| | | @Override |
| | | public synchronized void init(ProcessingEnvironment env) { |
| | | super.init(env); |
| | | this.typeHelper = new TypeHelper(env); |
| | | } |
| | | |
| | | @Override |
| | | public Set<String> getSupportedAnnotationTypes() { |
| | | return Sets.ofImmutableSet(AutoService.class.getName()); |
| | | } |
| | | |
| | | @Override |
| | | protected boolean processImpl(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
| | | if (roundEnv.processingOver()) { |
| | | generateConfigFiles(); |
| | | } else { |
| | | processAnnotations(annotations, roundEnv); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private void processAnnotations(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
| | | Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(AutoService.class); |
| | | |
| | | log(annotations.toString()); |
| | | log(elements.toString()); |
| | | |
| | | for (Element e : elements) { |
| | | TypeElement providerImplementer = (TypeElement) e; |
| | | AnnotationMirror annotationMirror = getAnnotationMirror(e, AutoService.class); |
| | | if (annotationMirror == null) { |
| | | continue; |
| | | } |
| | | Set<TypeMirror> typeMirrors = getValueFieldOfClasses(annotationMirror); |
| | | if (typeMirrors.isEmpty()) { |
| | | error("No service interfaces provided for element!", e, annotationMirror); |
| | | continue; |
| | | } |
| | | for (TypeMirror typeMirror : typeMirrors) { |
| | | String providerInterfaceName = typeHelper.getType(typeMirror); |
| | | Name providerImplementerName = providerImplementer.getQualifiedName(); |
| | | |
| | | log("provider interface: " + providerInterfaceName); |
| | | log("provider implementer: " + providerImplementerName); |
| | | |
| | | if (checkImplementer(providerImplementer, typeMirror)) { |
| | | providers.put(providerInterfaceName, typeHelper.getType(providerImplementer)); |
| | | } else { |
| | | String message = "ServiceProviders must implement their service provider interface. " |
| | | + providerImplementerName + " does not implement " + providerInterfaceName; |
| | | error(message, e, annotationMirror); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void generateConfigFiles() { |
| | | Filer filer = processingEnv.getFiler(); |
| | | |
| | | for (String providerInterface : providers.keySet()) { |
| | | String resourceFile = "META-INF/services/" + providerInterface; |
| | | log("Working on resource file: " + resourceFile); |
| | | try { |
| | | SortedSet<String> allServices = new TreeSet<>(); |
| | | try { |
| | | FileObject existingFile = filer.getResource(StandardLocation.CLASS_OUTPUT, "", resourceFile); |
| | | log("Looking for existing resource file at " + existingFile.toUri()); |
| | | Set<String> oldServices = ServicesFiles.readServiceFile(existingFile.openInputStream()); |
| | | log("Existing service entries: " + oldServices); |
| | | allServices.addAll(oldServices); |
| | | } catch (IOException e) { |
| | | log("Resource file did not already exist."); |
| | | } |
| | | |
| | | Set<String> newServices = new HashSet<>(providers.get(providerInterface)); |
| | | if (allServices.containsAll(newServices)) { |
| | | log("No new service entries being added."); |
| | | return; |
| | | } |
| | | |
| | | allServices.addAll(newServices); |
| | | log("New service file contents: " + allServices); |
| | | FileObject fileObject = filer.createResource(StandardLocation.CLASS_OUTPUT, "", resourceFile); |
| | | OutputStream out = fileObject.openOutputStream(); |
| | | ServicesFiles.writeServiceFile(allServices, out); |
| | | out.close(); |
| | | log("Wrote to: " + fileObject.toUri()); |
| | | } catch (IOException e) { |
| | | fatalError("Unable to create " + resourceFile + ", " + e); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Verifies {@link java.util.spi.LocaleServiceProvider} constraints on the concrete provider class. |
| | | * Note that these constraints are enforced at runtime via the ServiceLoader, |
| | | * we're just checking them at compile time to be extra nice to our users. |
| | | */ |
| | | private boolean checkImplementer(TypeElement providerImplementer, TypeMirror providerType) { |
| | | // TODO: We're currently only enforcing the subtype relationship |
| | | // constraint. It would be nice to enforce them all. |
| | | Types types = processingEnv.getTypeUtils(); |
| | | |
| | | return types.isSubtype(providerImplementer.asType(), providerType); |
| | | } |
| | | |
| | | /** |
| | | * 读å AutoService ä¸ç value å¼ |
| | | * |
| | | * @param annotationMirror AnnotationMirror |
| | | * @return value éå |
| | | */ |
| | | private Set<TypeMirror> getValueFieldOfClasses(AnnotationMirror annotationMirror) { |
| | | return getAnnotationValue(annotationMirror, "value") |
| | | .accept(new SimpleAnnotationValueVisitor8<Set<TypeMirror>, Void>() { |
| | | @Override |
| | | public Set<TypeMirror> visitType(TypeMirror typeMirror, Void v) { |
| | | Set<TypeMirror> declaredTypeSet = new HashSet<>(1); |
| | | declaredTypeSet.add(typeMirror); |
| | | return Collections.unmodifiableSet(declaredTypeSet); |
| | | } |
| | | |
| | | @Override |
| | | public Set<TypeMirror> visitArray( |
| | | List<? extends AnnotationValue> values, Void v) { |
| | | return values |
| | | .stream() |
| | | .flatMap(value -> value.accept(this, null).stream()) |
| | | .collect(Collectors.toSet()); |
| | | } |
| | | }, null); |
| | | } |
| | | |
| | | /** |
| | | * Returns a {@link ExecutableElement} and its associated {@link AnnotationValue} if such |
| | | * an element was either declared in the usage represented by the provided |
| | | * {@link AnnotationMirror}, or if such an element was defined with a default. |
| | | * |
| | | * @param annotationMirror AnnotationMirror |
| | | * @param elementName elementName |
| | | * @return AnnotationValue map |
| | | * @throws IllegalArgumentException if no element is defined with the given elementName. |
| | | */ |
| | | public AnnotationValue getAnnotationValue(AnnotationMirror annotationMirror, String elementName) { |
| | | Objects.requireNonNull(annotationMirror); |
| | | Objects.requireNonNull(elementName); |
| | | for (Map.Entry<ExecutableElement, AnnotationValue> entry : getAnnotationValuesWithDefaults(annotationMirror).entrySet()) { |
| | | if (entry.getKey().getSimpleName().contentEquals(elementName)) { |
| | | return entry.getValue(); |
| | | } |
| | | } |
| | | String name = typeHelper.getType(annotationMirror); |
| | | throw new IllegalArgumentException(String.format("@%s does not define an element %s()", name, elementName)); |
| | | } |
| | | |
| | | /** |
| | | * Returns the {@link AnnotationMirror}'s map of {@link AnnotationValue} indexed by {@link |
| | | * ExecutableElement}, supplying default values from the annotation if the annotation property has |
| | | * not been set. This is equivalent to {@link |
| | | * Elements#getElementValuesWithDefaults(AnnotationMirror)} but can be called statically without |
| | | * an {@link Elements} instance. |
| | | * |
| | | * <p>The iteration order of elements of the returned map will be the order in which the {@link |
| | | * ExecutableElement}s are defined in {@code annotation}'s {@linkplain |
| | | * AnnotationMirror#getAnnotationType() type}. |
| | | * |
| | | * @param annotation AnnotationMirror |
| | | * @return AnnotationValue Map |
| | | */ |
| | | public Map<ExecutableElement, AnnotationValue> getAnnotationValuesWithDefaults(AnnotationMirror annotation) { |
| | | Map<ExecutableElement, AnnotationValue> values = new HashMap<>(32); |
| | | Map<? extends ExecutableElement, ? extends AnnotationValue> declaredValues = annotation.getElementValues(); |
| | | for (ExecutableElement method : ElementFilter.methodsIn(annotation.getAnnotationType().asElement().getEnclosedElements())) { |
| | | // Must iterate and put in this order, to ensure consistency in generated code. |
| | | if (declaredValues.containsKey(method)) { |
| | | values.put(method, declaredValues.get(method)); |
| | | } else if (method.getDefaultValue() != null) { |
| | | values.put(method, method.getDefaultValue()); |
| | | } else { |
| | | String name = typeHelper.getType(method); |
| | | throw new IllegalStateException( |
| | | "Unset annotation value without default should never happen: " + name + '.' + method.getSimpleName() + "()"); |
| | | } |
| | | } |
| | | return Collections.unmodifiableMap(values); |
| | | } |
| | | |
| | | public AnnotationMirror getAnnotationMirror(Element element, Class<? extends Annotation> annotationClass) { |
| | | String annotationClassName = annotationClass.getCanonicalName(); |
| | | for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) { |
| | | String name = typeHelper.getType(annotationMirror); |
| | | if (name.contentEquals(annotationClassName)) { |
| | | return annotationMirror; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.auto.service; |
| | | |
| | | import java.io.*; |
| | | import java.nio.charset.Charset; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.Collection; |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * A helper class for reading and writing Services files. |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | class ServicesFiles { |
| | | private static final Charset UTF_8 = StandardCharsets.UTF_8; |
| | | |
| | | /** |
| | | * Reads the set of service classes from a service file. |
| | | * |
| | | * @param input not {@code null}. Closed after use. |
| | | * @return a not {@code null Set} of service class names. |
| | | * @throws IOException |
| | | */ |
| | | static Set<String> readServiceFile(InputStream input) throws IOException { |
| | | HashSet<String> serviceClasses = new HashSet<>(); |
| | | try ( |
| | | InputStreamReader isr = new InputStreamReader(input, UTF_8); |
| | | BufferedReader r = new BufferedReader(isr) |
| | | ) { |
| | | String line; |
| | | while ((line = r.readLine()) != null) { |
| | | int commentStart = line.indexOf('#'); |
| | | if (commentStart >= 0) { |
| | | line = line.substring(0, commentStart); |
| | | } |
| | | line = line.trim(); |
| | | if (!line.isEmpty()) { |
| | | serviceClasses.add(line); |
| | | } |
| | | } |
| | | return serviceClasses; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Writes the set of service class names to a service file. |
| | | * |
| | | * @param output not {@code null}. Not closed after use. |
| | | * @param services a not {@code null Collection} of service class names. |
| | | * @throws IOException |
| | | */ |
| | | static void writeServiceFile(Collection<String> services, OutputStream output) throws IOException { |
| | | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, UTF_8)); |
| | | for (String service : services) { |
| | | writer.write(service); |
| | | writer.newLine(); |
| | | } |
| | | writer.flush(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | org.springblade.core.auto.service.AutoServiceProcessor |
| | | org.springblade.core.auto.factories.AutoFactoriesProcessor |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0"?> |
| | | <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"> |
| | | <parent> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-boot</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <dependencies> |
| | | <!-- Blade --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-context</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-db</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-secure</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-cloud</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-cache</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-redis</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-log</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-mybatis</artifactId> |
| | | </dependency> |
| | | <!-- Auto --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.config; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.launch.props.BladePropertySource; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.context.annotation.EnableAspectJAutoProxy; |
| | | |
| | | /** |
| | | * bladeèªå¨é
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AutoConfiguration |
| | | @AllArgsConstructor |
| | | @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) |
| | | @BladePropertySource(value = "classpath:/blade-boot.yml") |
| | | public class BladeBootAutoConfiguration { |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.config; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.boot.error.ErrorType; |
| | | import org.springblade.core.boot.error.ErrorUtil; |
| | | import org.springblade.core.context.BladeContext; |
| | | import org.springblade.core.context.BladeRunnableWrapper; |
| | | import org.springblade.core.launch.props.BladeProperties; |
| | | import org.springblade.core.log.constant.EventConstant; |
| | | import org.springblade.core.log.event.ErrorLogEvent; |
| | | import org.springblade.core.log.model.LogError; |
| | | import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; |
| | | import org.springframework.boot.task.TaskExecutorCustomizer; |
| | | import org.springframework.boot.task.TaskSchedulerCustomizer; |
| | | import org.springframework.context.ApplicationEventPublisher; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.scheduling.annotation.AsyncConfigurerSupport; |
| | | import org.springframework.scheduling.annotation.EnableAsync; |
| | | import org.springframework.scheduling.annotation.EnableScheduling; |
| | | import org.springframework.util.ErrorHandler; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ThreadPoolExecutor; |
| | | |
| | | /** |
| | | * 弿¥å¤ç |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @Configuration |
| | | @EnableAsync |
| | | @EnableScheduling |
| | | @AllArgsConstructor |
| | | public class BladeExecutorConfiguration extends AsyncConfigurerSupport { |
| | | |
| | | private final BladeContext bladeContext; |
| | | private final BladeProperties bladeProperties; |
| | | private final ApplicationEventPublisher publisher; |
| | | |
| | | @Bean |
| | | public TaskExecutorCustomizer taskExecutorCustomizer() { |
| | | return taskExecutor -> { |
| | | taskExecutor.setThreadNamePrefix("async-task-"); |
| | | taskExecutor.setTaskDecorator(BladeRunnableWrapper::new); |
| | | taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); |
| | | }; |
| | | } |
| | | |
| | | @Bean |
| | | public TaskSchedulerCustomizer taskSchedulerCustomizer() { |
| | | return taskExecutor -> { |
| | | taskExecutor.setThreadNamePrefix("async-scheduler"); |
| | | taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); |
| | | taskExecutor.setErrorHandler(new BladeErrorHandler(bladeContext, bladeProperties, publisher)); |
| | | }; |
| | | } |
| | | |
| | | @Override |
| | | public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { |
| | | return new BladeAsyncUncaughtExceptionHandler(bladeContext, bladeProperties, publisher); |
| | | } |
| | | |
| | | @RequiredArgsConstructor |
| | | private static class BladeAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { |
| | | private final BladeContext bladeContext; |
| | | private final BladeProperties bladeProperties; |
| | | private final ApplicationEventPublisher eventPublisher; |
| | | |
| | | @Override |
| | | public void handleUncaughtException(@NonNull Throwable error, @NonNull Method method, @NonNull Object... params) { |
| | | log.error("Unexpected exception occurred invoking async method: {}", method, error); |
| | | LogError logError = new LogError(); |
| | | // æå¡ä¿¡æ¯ãç¯å¢ãå¼å¸¸ç±»å |
| | | logError.setParams(ErrorType.ASYNC.getType()); |
| | | logError.setEnv(bladeProperties.getEnv()); |
| | | logError.setServiceId(bladeProperties.getName()); |
| | | logError.setRequestUri(bladeContext.getRequestId()); |
| | | // å æ ä¿¡æ¯ |
| | | ErrorUtil.initErrorInfo(error, logError); |
| | | Map<String, Object> event = new HashMap<>(16); |
| | | event.put(EventConstant.EVENT_LOG, logError); |
| | | eventPublisher.publishEvent(new ErrorLogEvent(event)); |
| | | } |
| | | } |
| | | |
| | | @RequiredArgsConstructor |
| | | private static class BladeErrorHandler implements ErrorHandler { |
| | | private final BladeContext bladeContext; |
| | | private final BladeProperties bladeProperties; |
| | | private final ApplicationEventPublisher eventPublisher; |
| | | |
| | | @Override |
| | | public void handleError(@NonNull Throwable error) { |
| | | log.error("Unexpected scheduler exception", error); |
| | | LogError logError = new LogError(); |
| | | // æå¡ä¿¡æ¯ãç¯å¢ãå¼å¸¸ç±»å |
| | | logError.setParams(ErrorType.SCHEDULER.getType()); |
| | | logError.setServiceId(bladeProperties.getName()); |
| | | logError.setEnv(bladeProperties.getEnv()); |
| | | logError.setRequestUri(bladeContext.getRequestId()); |
| | | // å æ ä¿¡æ¯ |
| | | ErrorUtil.initErrorInfo(error, logError); |
| | | Map<String, Object> event = new HashMap<>(16); |
| | | event.put(EventConstant.EVENT_LOG, logError); |
| | | eventPublisher.publishEvent(new ErrorLogEvent(event)); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.config; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.retry.interceptor.RetryInterceptorBuilder; |
| | | import org.springframework.retry.interceptor.RetryOperationsInterceptor; |
| | | |
| | | /** |
| | | * éè¯æºå¶ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AutoConfiguration |
| | | public class BladeRetryConfiguration { |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean(name = "configServerRetryInterceptor") |
| | | public RetryOperationsInterceptor configServerRetryInterceptor() { |
| | | log.info(String.format( |
| | | "configServerRetryInterceptor: Changing backOffOptions " + |
| | | "to initial: %s, multiplier: %s, maxInterval: %s", |
| | | 1000, 1.2, 5000)); |
| | | return RetryInterceptorBuilder |
| | | .stateless() |
| | | .backOffOptions(1000, 1.2, 5000) |
| | | .maxAttempts(10) |
| | | .build(); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.config; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.boot.props.BladeFileProperties; |
| | | import org.springblade.core.boot.props.BladeUploadProperties; |
| | | import org.springblade.core.boot.resolver.TokenArgumentResolver; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.core.Ordered; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.web.method.support.HandlerMethodArgumentResolver; |
| | | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; |
| | | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * WEBé
ç½® |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AutoConfiguration |
| | | @Order(Ordered.HIGHEST_PRECEDENCE) |
| | | @AllArgsConstructor |
| | | @EnableConfigurationProperties({ |
| | | BladeUploadProperties.class, BladeFileProperties.class |
| | | }) |
| | | public class BladeWebMvcConfiguration implements WebMvcConfigurer { |
| | | |
| | | private final BladeUploadProperties bladeUploadProperties; |
| | | |
| | | @Override |
| | | public void addResourceHandlers(ResourceHandlerRegistry registry) { |
| | | String path = bladeUploadProperties.getSavePath(); |
| | | registry.addResourceHandler("/upload/**") |
| | | .addResourceLocations("file:" + path + "/upload/"); |
| | | } |
| | | |
| | | @Override |
| | | public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { |
| | | argumentResolvers.add(new TokenArgumentResolver()); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.config; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springblade.core.boot.request.BladeRequestFilter; |
| | | import org.springblade.core.boot.request.RequestProperties; |
| | | import org.springblade.core.boot.request.XssProperties; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.core.Ordered; |
| | | |
| | | import javax.servlet.DispatcherType; |
| | | |
| | | /** |
| | | * è¿æ»¤å¨é
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AutoConfiguration |
| | | @AllArgsConstructor |
| | | @EnableConfigurationProperties({RequestProperties.class, XssProperties.class}) |
| | | public class RequestConfiguration { |
| | | |
| | | private final RequestProperties requestProperties; |
| | | private final XssProperties xssProperties; |
| | | |
| | | /** |
| | | * å
¨å±è¿æ»¤å¨ |
| | | */ |
| | | @Bean |
| | | public FilterRegistrationBean<BladeRequestFilter> bladeFilterRegistration() { |
| | | FilterRegistrationBean<BladeRequestFilter> registration = new FilterRegistrationBean<>(); |
| | | registration.setDispatcherTypes(DispatcherType.REQUEST); |
| | | registration.setFilter(new BladeRequestFilter(requestProperties, xssProperties)); |
| | | registration.addUrlPatterns("/*"); |
| | | registration.setName("bladeRequestFilter"); |
| | | registration.setOrder(Ordered.LOWEST_PRECEDENCE); |
| | | return registration; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.ctrl; |
| | | |
| | | import org.springblade.core.boot.file.LocalFile; |
| | | import org.springblade.core.boot.file.BladeFileUtil; |
| | | import org.springblade.core.secure.BladeUser; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.utils.Charsets; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.core.io.FileSystemResource; |
| | | import org.springframework.core.io.Resource; |
| | | import org.springframework.core.io.support.ResourceRegion; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | import org.springframework.web.util.UriUtils; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Bladeæ§å¶å¨å°è£
ç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class BladeController { |
| | | |
| | | /** |
| | | * ============================ REQUEST ================================================= |
| | | */ |
| | | |
| | | @Autowired |
| | | private HttpServletRequest request; |
| | | |
| | | /** |
| | | * è·årequest |
| | | */ |
| | | public HttpServletRequest getRequest() { |
| | | return this.request; |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åç¨æ· |
| | | * |
| | | * @return |
| | | */ |
| | | public BladeUser getUser() { |
| | | return AuthUtil.getUser(); |
| | | } |
| | | |
| | | /** ============================ API_RESULT ================================================= */ |
| | | |
| | | /** |
| | | * è¿åApiResult |
| | | * |
| | | * @param data |
| | | * @return R |
| | | */ |
| | | public <T> R<T> data(T data) { |
| | | return R.data(data); |
| | | } |
| | | |
| | | /** |
| | | * è¿åApiResult |
| | | * |
| | | * @param data |
| | | * @param message |
| | | * @return R |
| | | */ |
| | | public <T> R<T> data(T data, String message) { |
| | | return R.data(data, message); |
| | | } |
| | | |
| | | /** |
| | | * è¿åApiResult |
| | | * |
| | | * @param data |
| | | * @param message |
| | | * @param code |
| | | * @return R |
| | | */ |
| | | public <T> R<T> data(T data, String message, int code) { |
| | | return R.data(code, data, message); |
| | | } |
| | | |
| | | /** |
| | | * è¿åApiResult |
| | | * |
| | | * @param message |
| | | * @return R |
| | | */ |
| | | public R success(String message) { |
| | | return R.success(message); |
| | | } |
| | | |
| | | /** |
| | | * è¿åApiResult |
| | | * |
| | | * @param message |
| | | * @return R |
| | | */ |
| | | public R fail(String message) { |
| | | return R.fail(message); |
| | | } |
| | | |
| | | /** |
| | | * è¿åApiResult |
| | | * |
| | | * @param flag |
| | | * @return R |
| | | */ |
| | | public R status(boolean flag) { |
| | | return R.status(flag); |
| | | } |
| | | |
| | | |
| | | /**============================ FILE ================================================= */ |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param file |
| | | * @return |
| | | */ |
| | | public LocalFile getFile(MultipartFile file) { |
| | | return BladeFileUtil.getFile(file); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param file |
| | | * @param dir |
| | | * @return |
| | | */ |
| | | public LocalFile getFile(MultipartFile file, String dir) { |
| | | return BladeFileUtil.getFile(file, dir); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param file |
| | | * @param dir |
| | | * @param path |
| | | * @param virtualPath |
| | | * @return |
| | | */ |
| | | public LocalFile getFile(MultipartFile file, String dir, String path, String virtualPath) { |
| | | return BladeFileUtil.getFile(file, dir, path, virtualPath); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param files |
| | | * @return |
| | | */ |
| | | public List<LocalFile> getFiles(List<MultipartFile> files) { |
| | | return BladeFileUtil.getFiles(files); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param files |
| | | * @param dir |
| | | * @return |
| | | */ |
| | | public List<LocalFile> getFiles(List<MultipartFile> files, String dir) { |
| | | return BladeFileUtil.getFiles(files, dir); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param files |
| | | * @param path |
| | | * @param virtualPath |
| | | * @return |
| | | */ |
| | | public List<LocalFile> getFiles(List<MultipartFile> files, String dir, String path, String virtualPath) { |
| | | return BladeFileUtil.getFiles(files, dir, path, virtualPath); |
| | | } |
| | | /** |
| | | * ä¸è½½æä»¶ |
| | | * |
| | | * @param file æä»¶ |
| | | * @return {ResponseEntity} |
| | | * @throws IOException ioå¼å¸¸ |
| | | */ |
| | | protected ResponseEntity<ResourceRegion> download(File file) throws IOException { |
| | | String fileName = file.getName(); |
| | | return download(file, fileName); |
| | | } |
| | | |
| | | /** |
| | | * ä¸è½½ |
| | | * |
| | | * @param file æä»¶ |
| | | * @param fileName çæçæä»¶å |
| | | * @return {ResponseEntity} |
| | | * @throws IOException ioå¼å¸¸ |
| | | */ |
| | | protected ResponseEntity<ResourceRegion> download(File file, String fileName) throws IOException { |
| | | Resource resource = new FileSystemResource(file); |
| | | return download(resource, fileName); |
| | | } |
| | | |
| | | /** |
| | | * ä¸è½½ |
| | | * |
| | | * @param resource èµæº |
| | | * @param fileName çæçæä»¶å |
| | | * @return {ResponseEntity} |
| | | * @throws IOException ioå¼å¸¸ |
| | | */ |
| | | protected ResponseEntity<ResourceRegion> download(Resource resource, String fileName) throws IOException { |
| | | HttpServletRequest request = WebUtil.getRequest(); |
| | | String header = request.getHeader(HttpHeaders.USER_AGENT); |
| | | // é¿å
空æé |
| | | header = header == null ? StringPool.EMPTY : header.toUpperCase(); |
| | | HttpStatus status; |
| | | String msie= "MSIE"; |
| | | String trident= "TRIDENT"; |
| | | String edge= "EDGE"; |
| | | if (header.contains(msie) || header.contains(trident) || header.contains(edge)) { |
| | | status = HttpStatus.OK; |
| | | } else { |
| | | status = HttpStatus.CREATED; |
| | | } |
| | | // æç¹ç»ä¼ |
| | | long position = 0; |
| | | long count = resource.contentLength(); |
| | | String range = request.getHeader(HttpHeaders.RANGE); |
| | | if (null != range) { |
| | | status = HttpStatus.PARTIAL_CONTENT; |
| | | String[] rangeRange = range.replace("bytes=", StringPool.EMPTY).split(StringPool.DASH); |
| | | position = Long.parseLong(rangeRange[0]); |
| | | if (rangeRange.length > 1) { |
| | | long end = Long.parseLong(rangeRange[1]); |
| | | count = end - position + 1; |
| | | } |
| | | } |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); |
| | | String encodeFileName = UriUtils.encode(fileName, Charsets.UTF_8); |
| | | // å
¼å®¹åç§æµè§å¨ä¸è½½ï¼ |
| | | // https://blog.robotshell.org/2012/deal-with-http-header-encoding-for-file-download/ |
| | | String disposition = "attachment;" + |
| | | "filename=\"" + encodeFileName + "\";" + |
| | | "filename*=utf-8''" + encodeFileName; |
| | | headers.set(HttpHeaders.CONTENT_DISPOSITION, disposition); |
| | | return new ResponseEntity<>(new ResourceRegion(resource, position, count), headers, status); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.boot.error; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonCreator; |
| | | import com.fasterxml.jackson.annotation.JsonValue; |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | /** |
| | | * å¼å¸¸ç±»å |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | @RequiredArgsConstructor |
| | | public enum ErrorType { |
| | | /** |
| | | * å¼å¸¸ç±»å |
| | | */ |
| | | REQUEST("request"), |
| | | ASYNC("async"), |
| | | SCHEDULER("scheduler"), |
| | | WEB_SOCKET("websocket"), |
| | | OTHER("other"); |
| | | |
| | | @JsonValue |
| | | private final String type; |
| | | |
| | | @Nullable |
| | | @JsonCreator |
| | | public static ErrorType of(String type) { |
| | | ErrorType[] values = ErrorType.values(); |
| | | for (ErrorType errorType : values) { |
| | | if (errorType.type.equals(type)) { |
| | | return errorType; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.boot.error; |
| | | |
| | | import org.springblade.core.log.model.LogError; |
| | | import org.springblade.core.tool.utils.DateUtil; |
| | | import org.springblade.core.tool.utils.Exceptions; |
| | | import org.springblade.core.tool.utils.ObjectUtil; |
| | | |
| | | /** |
| | | * å¼å¸¸å·¥å
·ç±» |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class ErrorUtil { |
| | | |
| | | /** |
| | | * åå§åå¼å¸¸ä¿¡æ¯ |
| | | * |
| | | * @param error å¼å¸¸ |
| | | * @param event å¼å¸¸äºä»¶å°è£
|
| | | */ |
| | | public static void initErrorInfo(Throwable error, LogError event) { |
| | | // å æ ä¿¡æ¯ |
| | | event.setStackTrace(Exceptions.getStackTraceAsString(error)); |
| | | event.setExceptionName(error.getClass().getName()); |
| | | event.setMessage(error.getMessage()); |
| | | event.setCreateTime(DateUtil.now()); |
| | | StackTraceElement[] elements = error.getStackTrace(); |
| | | if (ObjectUtil.isNotEmpty(elements)) { |
| | | // æ¥éçç±»ä¿¡æ¯ |
| | | StackTraceElement element = elements[0]; |
| | | event.setMethodClass(element.getClassName()); |
| | | event.setFileName(element.getFileName()); |
| | | event.setMethodName(element.getMethodName()); |
| | | event.setLineNumber(element.getLineNumber()); |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.file; |
| | | |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * æä»¶å·¥å
·ç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class BladeFileUtil { |
| | | |
| | | /** |
| | | * å®ä¹å
许ä¸ä¼ çæä»¶æ©å±å |
| | | */ |
| | | private static final HashMap<String, String> EXT_MAP = new HashMap<>(); |
| | | private static final String IS_DIR = "is_dir"; |
| | | private static final String FILE_NAME = "filename"; |
| | | private static final String FILE_SIZE = "filesize"; |
| | | |
| | | /** |
| | | * å¾çæ©å±å |
| | | */ |
| | | private static final String[] FILE_TYPES = new String[]{"gif", "jpg", "jpeg", "png", "bmp"}; |
| | | |
| | | static { |
| | | EXT_MAP.put("image", ".gif,.jpg,.jpeg,.png,.bmp,.JPG,.JPEG,.PNG"); |
| | | EXT_MAP.put("flash", ".swf,.flv"); |
| | | EXT_MAP.put("media", ".swf,.flv,.mp3,.mp4,.wav,.wma,.wmv,.mid,.avi,.mpg,.asf,.rm,.rmvb"); |
| | | EXT_MAP.put("file", ".doc,.docx,.xls,.xlsx,.ppt,.htm,.html,.txt,.zip,.rar,.gz,.bz2"); |
| | | EXT_MAP.put("allfile", ".gif,.jpg,.jpeg,.png,.bmp,.swf,.flv,.mp3,.mp4,.wav,.wma,.wmv,.mid,.avi,.mpg,.asf,.rm,.rmvb,.doc,.docx,.xls,.xlsx,.ppt,.htm,.html,.txt,.zip,.rar,.gz,.bz2"); |
| | | } |
| | | |
| | | /** |
| | | * è·åæä»¶åç¼ |
| | | * |
| | | * @param fileName æä»¶å |
| | | * @return String è¿ååç¼ |
| | | */ |
| | | public static String getFileExt(String fileName) { |
| | | return fileName.substring(fileName.lastIndexOf(StringPool.DOT)); |
| | | } |
| | | |
| | | /** |
| | | * æµè¯æä»¶åç¼ åªè®©æå®åç¼çæä»¶ä¸ä¼ ï¼åjsp,war,shçå±é©çåç¼ç¦æ¢ |
| | | * |
| | | * @param dir ç®å½ |
| | | * @param fileName æä»¶å |
| | | * @return è¿åæåä¸å¦ |
| | | */ |
| | | public static boolean testExt(String dir, String fileName) { |
| | | String fileExt = getFileExt(fileName); |
| | | String ext = EXT_MAP.get(dir); |
| | | return StringUtil.isNotBlank(ext) && (ext.contains(fileExt.toLowerCase()) || ext.contains(fileExt.toUpperCase())); |
| | | } |
| | | |
| | | /** |
| | | * æä»¶ç®¡çæåº |
| | | */ |
| | | public enum FileSort { |
| | | |
| | | /** |
| | | * å¤§å° |
| | | */ |
| | | size, |
| | | |
| | | /** |
| | | * ç±»å |
| | | */ |
| | | type, |
| | | |
| | | /** |
| | | * åç§° |
| | | */ |
| | | name; |
| | | |
| | | /** |
| | | * ææ¬æåºè½¬æ¢ææä¸¾ |
| | | * |
| | | * @param sort |
| | | * @return |
| | | */ |
| | | public static FileSort of(String sort) { |
| | | try { |
| | | return FileSort.valueOf(sort); |
| | | } catch (Exception e) { |
| | | return FileSort.name; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static class NameComparator implements Comparator { |
| | | @Override |
| | | public int compare(Object a, Object b) { |
| | | Hashtable hashA = (Hashtable) a; |
| | | Hashtable hashB = (Hashtable) b; |
| | | if (((Boolean) hashA.get(IS_DIR)) && !((Boolean) hashB.get(IS_DIR))) { |
| | | return -1; |
| | | } else if (!((Boolean) hashA.get(IS_DIR)) && ((Boolean) hashB.get(IS_DIR))) { |
| | | return 1; |
| | | } else { |
| | | return ((String) hashA.get(FILE_NAME)).compareTo((String) hashB.get(FILE_NAME)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static class SizeComparator implements Comparator { |
| | | @Override |
| | | public int compare(Object a, Object b) { |
| | | Hashtable hashA = (Hashtable) a; |
| | | Hashtable hashB = (Hashtable) b; |
| | | if (((Boolean) hashA.get(IS_DIR)) && !((Boolean) hashB.get(IS_DIR))) { |
| | | return -1; |
| | | } else if (!((Boolean) hashA.get(IS_DIR)) && ((Boolean) hashB.get(IS_DIR))) { |
| | | return 1; |
| | | } else { |
| | | if (((Long) hashA.get(FILE_SIZE)) > ((Long) hashB.get(FILE_SIZE))) { |
| | | return 1; |
| | | } else if (((Long) hashA.get(FILE_SIZE)) < ((Long) hashB.get(FILE_SIZE))) { |
| | | return -1; |
| | | } else { |
| | | return 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static class TypeComparator implements Comparator { |
| | | @Override |
| | | public int compare(Object a, Object b) { |
| | | Hashtable hashA = (Hashtable) a; |
| | | Hashtable hashB = (Hashtable) b; |
| | | if (((Boolean) hashA.get(IS_DIR)) && !((Boolean) hashB.get(IS_DIR))) { |
| | | return -1; |
| | | } else if (!((Boolean) hashA.get(IS_DIR)) && ((Boolean) hashB.get(IS_DIR))) { |
| | | return 1; |
| | | } else { |
| | | return ((String) hashA.get("filetype")).compareTo((String) hashB.get("filetype")); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static String formatUrl(String url) { |
| | | return url.replaceAll("\\\\", "/"); |
| | | } |
| | | |
| | | |
| | | /********************************BladeFileå°è£
********************************************************/ |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param file æä»¶ |
| | | * @return BladeFile |
| | | */ |
| | | public static LocalFile getFile(MultipartFile file) { |
| | | return getFile(file, "image", null, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param file æä»¶ |
| | | * @param dir ç®å½ |
| | | * @return BladeFile |
| | | */ |
| | | public static LocalFile getFile(MultipartFile file, String dir) { |
| | | return getFile(file, dir, null, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param file æä»¶ |
| | | * @param dir ç®å½ |
| | | * @param path è·¯å¾ |
| | | * @param virtualPath èæè·¯å¾ |
| | | * @return BladeFile |
| | | */ |
| | | public static LocalFile getFile(MultipartFile file, String dir, String path, String virtualPath) { |
| | | return new LocalFile(file, dir, path, virtualPath); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param files æä»¶éå |
| | | * @return BladeFile |
| | | */ |
| | | public static List<LocalFile> getFiles(List<MultipartFile> files) { |
| | | return getFiles(files, "image", null, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param files æä»¶éå |
| | | * @param dir ç®å½ |
| | | * @return BladeFile |
| | | */ |
| | | public static List<LocalFile> getFiles(List<MultipartFile> files, String dir) { |
| | | return getFiles(files, dir, null, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åBladeFileå°è£
ç±» |
| | | * |
| | | * @param files æä»¶éå |
| | | * @param path è·¯å¾ |
| | | * @param virtualPath èæè·¯å¾ |
| | | * @return BladeFile |
| | | */ |
| | | public static List<LocalFile> getFiles(List<MultipartFile> files, String dir, String path, String virtualPath) { |
| | | List<LocalFile> list = new ArrayList<>(); |
| | | for (MultipartFile file : files) { |
| | | list.add(new LocalFile(file, dir, path, virtualPath)); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.file; |
| | | |
| | | import java.io.File; |
| | | |
| | | /** |
| | | * æä»¶ç®¡çç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class FileProxyManager { |
| | | private IFileProxy defaultFileProxyFactory = new LocalFileProxyFactory(); |
| | | |
| | | private static final FileProxyManager ME = new FileProxyManager(); |
| | | |
| | | public static FileProxyManager me() { |
| | | return ME; |
| | | } |
| | | |
| | | public IFileProxy getDefaultFileProxyFactory() { |
| | | return defaultFileProxyFactory; |
| | | } |
| | | |
| | | public void setDefaultFileProxyFactory(IFileProxy defaultFileProxyFactory) { |
| | | this.defaultFileProxyFactory = defaultFileProxyFactory; |
| | | } |
| | | |
| | | public String[] path(File file, String dir) { |
| | | return defaultFileProxyFactory.path(file, dir); |
| | | } |
| | | |
| | | public File rename(File file, String path) { |
| | | return defaultFileProxyFactory.rename(file, path); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.file; |
| | | |
| | | import java.io.File; |
| | | |
| | | /** |
| | | * æä»¶ä»£çæ¥å£ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface IFileProxy { |
| | | |
| | | /** |
| | | * è¿åè·¯å¾[ç©çè·¯å¾][èæè·¯å¾] |
| | | * |
| | | * @param file æä»¶ |
| | | * @param dir ç®å½ |
| | | * @return |
| | | */ |
| | | String[] path(File file, String dir); |
| | | |
| | | /** |
| | | * æä»¶éå½åçç¥ |
| | | * |
| | | * @param file æä»¶ |
| | | * @param path è·¯å¾ |
| | | * @return |
| | | */ |
| | | File rename(File file, String path); |
| | | |
| | | /** |
| | | * å¾çå缩 |
| | | * |
| | | * @param path è·¯å¾ |
| | | */ |
| | | void compress(String path); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.file; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonIgnore; |
| | | import lombok.Data; |
| | | import org.springblade.core.boot.props.BladeFileProperties; |
| | | import org.springblade.core.tool.utils.DateUtil; |
| | | import org.springblade.core.tool.utils.SpringUtil; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * ä¸ä¼ æä»¶å°è£
|
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | public class LocalFile { |
| | | /** |
| | | * ä¸ä¼ æä»¶å¨é件表ä¸çid |
| | | */ |
| | | private Object fileId; |
| | | |
| | | /** |
| | | * ä¸ä¼ æä»¶ |
| | | */ |
| | | @JsonIgnore |
| | | private MultipartFile file; |
| | | |
| | | /** |
| | | * æä»¶å¤ç½å°å |
| | | */ |
| | | private String domain; |
| | | |
| | | /** |
| | | * ä¸ä¼ åç±»æä»¶å¤¹ |
| | | */ |
| | | private String dir; |
| | | |
| | | /** |
| | | * ä¸ä¼ ç©çè·¯å¾ |
| | | */ |
| | | private String uploadPath; |
| | | |
| | | /** |
| | | * ä¸ä¼ èæè·¯å¾ |
| | | */ |
| | | private String uploadVirtualPath; |
| | | |
| | | /** |
| | | * æä»¶å |
| | | */ |
| | | private String fileName; |
| | | |
| | | /** |
| | | * ç宿件å |
| | | */ |
| | | private String originalFileName; |
| | | |
| | | /** |
| | | * æä»¶é
ç½® |
| | | */ |
| | | private static BladeFileProperties fileProperties; |
| | | |
| | | private static BladeFileProperties getBladeFileProperties() { |
| | | if (fileProperties == null) { |
| | | fileProperties = SpringUtil.getBean(BladeFileProperties.class); |
| | | } |
| | | return fileProperties; |
| | | } |
| | | |
| | | public LocalFile(MultipartFile file, String dir) { |
| | | this.dir = dir; |
| | | this.file = file; |
| | | this.fileName = file.getName(); |
| | | this.originalFileName = file.getOriginalFilename(); |
| | | this.domain = getBladeFileProperties().getUploadDomain(); |
| | | this.uploadPath = BladeFileUtil.formatUrl(File.separator + getBladeFileProperties().getUploadRealPath() + File.separator + dir + File.separator + DateUtil.format(DateUtil.now(), "yyyyMMdd") + File.separator + this.originalFileName); |
| | | this.uploadVirtualPath = BladeFileUtil.formatUrl(getBladeFileProperties().getUploadCtxPath().replace(getBladeFileProperties().getContextPath(), "") + File.separator + dir + File.separator + DateUtil.format(DateUtil.now(), "yyyyMMdd") + File.separator + this.originalFileName); |
| | | } |
| | | |
| | | public LocalFile(MultipartFile file, String dir, String uploadPath, String uploadVirtualPath) { |
| | | this(file, dir); |
| | | if (null != uploadPath) { |
| | | this.uploadPath = BladeFileUtil.formatUrl(uploadPath); |
| | | this.uploadVirtualPath = BladeFileUtil.formatUrl(uploadVirtualPath); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å¾çä¸ä¼ |
| | | */ |
| | | public void transfer() { |
| | | transfer(getBladeFileProperties().getCompress()); |
| | | } |
| | | |
| | | /** |
| | | * å¾çä¸ä¼ |
| | | * |
| | | * @param compress æ¯å¦å缩 |
| | | */ |
| | | public void transfer(boolean compress) { |
| | | IFileProxy fileFactory = FileProxyManager.me().getDefaultFileProxyFactory(); |
| | | this.transfer(fileFactory, compress); |
| | | } |
| | | |
| | | /** |
| | | * å¾çä¸ä¼ |
| | | * |
| | | * @param fileFactory æä»¶ä¸ä¼ å·¥åç±» |
| | | * @param compress æ¯å¦å缩 |
| | | */ |
| | | public void transfer(IFileProxy fileFactory, boolean compress) { |
| | | try { |
| | | File file = new File(uploadPath); |
| | | |
| | | if (null != fileFactory) { |
| | | String[] path = fileFactory.path(file, dir); |
| | | this.uploadPath = path[0]; |
| | | this.uploadVirtualPath = path[1]; |
| | | file = fileFactory.rename(file, path[0]); |
| | | } |
| | | |
| | | File pfile = file.getParentFile(); |
| | | if (!pfile.exists()) { |
| | | pfile.mkdirs(); |
| | | } |
| | | |
| | | this.file.transferTo(file); |
| | | |
| | | if (compress) { |
| | | fileFactory.compress(this.uploadPath); |
| | | } |
| | | |
| | | } catch (IllegalStateException | IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.file; |
| | | |
| | | import org.springblade.core.boot.props.BladeFileProperties; |
| | | import org.springblade.core.tool.utils.DateUtil; |
| | | import org.springblade.core.tool.utils.ImageUtil; |
| | | import org.springblade.core.tool.utils.SpringUtil; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileNotFoundException; |
| | | import java.io.FileOutputStream; |
| | | |
| | | /** |
| | | * æä»¶ä»£çç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class LocalFileProxyFactory implements IFileProxy { |
| | | |
| | | /** |
| | | * æä»¶é
ç½® |
| | | */ |
| | | private static BladeFileProperties fileProperties; |
| | | |
| | | private static BladeFileProperties getBladeFileProperties() { |
| | | if (fileProperties == null) { |
| | | fileProperties = SpringUtil.getBean(BladeFileProperties.class); |
| | | } |
| | | return fileProperties; |
| | | } |
| | | |
| | | @Override |
| | | public File rename(File f, String path) { |
| | | File dest = new File(path); |
| | | f.renameTo(dest); |
| | | return dest; |
| | | } |
| | | |
| | | @Override |
| | | public String[] path(File f, String dir) { |
| | | //é¿å
ç½ç»å»¶è¿å¯¼è´æ¶é´ä¸åæ¥ |
| | | long time = System.nanoTime(); |
| | | |
| | | StringBuilder uploadPath = new StringBuilder() |
| | | .append(getFileDir(dir, getBladeFileProperties().getUploadRealPath())) |
| | | .append(time) |
| | | .append(getFileExt(f.getName())); |
| | | |
| | | StringBuilder virtualPath = new StringBuilder() |
| | | .append(getFileDir(dir, getBladeFileProperties().getUploadCtxPath())) |
| | | .append(time) |
| | | .append(getFileExt(f.getName())); |
| | | |
| | | return new String[]{BladeFileUtil.formatUrl(uploadPath.toString()), BladeFileUtil.formatUrl(virtualPath.toString())}; |
| | | } |
| | | |
| | | /** |
| | | * è·åæä»¶åç¼ |
| | | * |
| | | * @param fileName æä»¶å |
| | | * @return æä»¶åç¼ |
| | | */ |
| | | public static String getFileExt(String fileName) { |
| | | if (!fileName.contains(StringPool.DOT)) { |
| | | return ".jpg"; |
| | | } else { |
| | | return fileName.substring(fileName.lastIndexOf(StringPool.DOT)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åæä»¶ä¿åå°å |
| | | * |
| | | * @param dir ç®å½ |
| | | * @param saveDir ä¿åç®å½ |
| | | * @return å°å |
| | | */ |
| | | public static String getFileDir(String dir, String saveDir) { |
| | | StringBuilder newFileDir = new StringBuilder(); |
| | | newFileDir.append(saveDir) |
| | | .append(File.separator).append(dir).append(File.separator).append(DateUtil.format(DateUtil.now(), "yyyyMMdd")) |
| | | .append(File.separator); |
| | | return newFileDir.toString(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å¾çå缩 |
| | | * |
| | | * @param path æä»¶å°å |
| | | */ |
| | | @Override |
| | | public void compress(String path) { |
| | | try { |
| | | ImageUtil.zoomScale(ImageUtil.readImage(path), new FileOutputStream(new File(path)), null, getBladeFileProperties().getCompressScale(), getBladeFileProperties().getCompressFlag()); |
| | | } catch (FileNotFoundException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.boot.props; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | /** |
| | | * BladeFileProperties |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @ConfigurationProperties("blade.file") |
| | | public class BladeFileProperties { |
| | | |
| | | /** |
| | | * è¿ç¨ä¸ä¼ æ¨¡å¼ |
| | | */ |
| | | private boolean remoteMode = false; |
| | | |
| | | /** |
| | | * å¤ç½å°å |
| | | */ |
| | | private String uploadDomain = "http://127.0.0.1:8999"; |
| | | |
| | | /** |
| | | * ä¸ä¼ ä¸è½½è·¯å¾(ç©çè·¯å¾) |
| | | */ |
| | | private String remotePath = System.getProperty("user.dir") + "/target/blade"; |
| | | |
| | | /** |
| | | * ä¸ä¼ è·¯å¾(ç¸å¯¹è·¯å¾) |
| | | */ |
| | | private String uploadPath = "/upload"; |
| | | |
| | | /** |
| | | * ä¸è½½è·¯å¾ |
| | | */ |
| | | private String downloadPath = "/download"; |
| | | |
| | | /** |
| | | * å¾çå缩 |
| | | */ |
| | | private Boolean compress = false; |
| | | |
| | | /** |
| | | * å¾çå缩æ¯ä¾ |
| | | */ |
| | | private Double compressScale = 2.00; |
| | | |
| | | /** |
| | | * å¾ç缩æ¾éæ©:trueæ¾å¤§;falseç¼©å° |
| | | */ |
| | | private Boolean compressFlag = false; |
| | | |
| | | /** |
| | | * 项ç®ç©çè·¯å¾ |
| | | */ |
| | | private String realPath = System.getProperty("user.dir"); |
| | | |
| | | /** |
| | | * 项ç®ç¸å¯¹è·¯å¾ |
| | | */ |
| | | private String contextPath = "/"; |
| | | |
| | | |
| | | public String getUploadRealPath() { |
| | | return (remoteMode ? remotePath : realPath) + uploadPath; |
| | | } |
| | | |
| | | public String getUploadCtxPath() { |
| | | return contextPath + uploadPath; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.props; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import org.springblade.core.tool.utils.PathUtil; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.cloud.context.config.annotation.RefreshScope; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | |
| | | /** |
| | | * æä»¶ä¸ä¼ é
ç½® |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @RefreshScope |
| | | @ConfigurationProperties("blade.upload") |
| | | public class BladeUploadProperties { |
| | | |
| | | /** |
| | | * æä»¶ä¿åç®å½ï¼é»è®¤ï¼jar å
å级ç®å½ |
| | | */ |
| | | @Nullable |
| | | private String savePath = PathUtil.getJarPath(); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.request; |
| | | |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.MediaType; |
| | | |
| | | import javax.servlet.ReadListener; |
| | | import javax.servlet.ServletInputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletRequestWrapper; |
| | | import java.io.BufferedReader; |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStreamReader; |
| | | |
| | | /** |
| | | * å
¨å±Requestå
è£
|
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class BladeHttpServletRequestWrapper extends HttpServletRequestWrapper { |
| | | |
| | | /** |
| | | * 没被å
è£
è¿çHttpServletRequestï¼ç¹æ®åºæ¯,éè¦èªå·±è¿æ»¤ï¼ |
| | | */ |
| | | private final HttpServletRequest orgRequest; |
| | | /** |
| | | * ç¼åæ¥æ,æ¯æå¤æ¬¡è¯»åæµ |
| | | */ |
| | | private byte[] body; |
| | | |
| | | |
| | | public BladeHttpServletRequestWrapper(HttpServletRequest request) { |
| | | super(request); |
| | | orgRequest = request; |
| | | } |
| | | |
| | | @Override |
| | | public BufferedReader getReader() throws IOException { |
| | | return new BufferedReader(new InputStreamReader(getInputStream())); |
| | | } |
| | | |
| | | @Override |
| | | public ServletInputStream getInputStream() throws IOException { |
| | | if (super.getHeader(HttpHeaders.CONTENT_TYPE) == null) { |
| | | return super.getInputStream(); |
| | | } |
| | | |
| | | if (super.getHeader(HttpHeaders.CONTENT_TYPE).startsWith(MediaType.MULTIPART_FORM_DATA_VALUE)) { |
| | | return super.getInputStream(); |
| | | } |
| | | |
| | | if (body == null) { |
| | | body = WebUtil.getRequestBody(super.getInputStream()).getBytes(); |
| | | } |
| | | |
| | | final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body); |
| | | |
| | | return new ServletInputStream() { |
| | | |
| | | @Override |
| | | public int read() { |
| | | return byteArrayInputStream.read(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isFinished() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isReady() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public void setReadListener(ReadListener readListener) { |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * è·ååå§request |
| | | * |
| | | * @return HttpServletRequest |
| | | */ |
| | | public HttpServletRequest getOrgRequest() { |
| | | return orgRequest; |
| | | } |
| | | |
| | | /** |
| | | * è·ååå§request |
| | | * |
| | | * @param request request |
| | | * @return HttpServletRequest |
| | | */ |
| | | public static HttpServletRequest getOrgRequest(HttpServletRequest request) { |
| | | if (request instanceof BladeHttpServletRequestWrapper) { |
| | | return ((BladeHttpServletRequestWrapper) request).getOrgRequest(); |
| | | } |
| | | return request; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.request; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.util.AntPathMatcher; |
| | | |
| | | import javax.servlet.*; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * Requestå
¨å±è¿æ»¤ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AllArgsConstructor |
| | | public class BladeRequestFilter implements Filter { |
| | | |
| | | private final RequestProperties requestProperties; |
| | | private final XssProperties xssProperties; |
| | | private final AntPathMatcher antPathMatcher = new AntPathMatcher(); |
| | | |
| | | @Override |
| | | public void init(FilterConfig config) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { |
| | | String path = ((HttpServletRequest) request).getServletPath(); |
| | | // è·³è¿ Request å
è£
|
| | | if (!requestProperties.getEnabled() || isRequestSkip(path)) { |
| | | chain.doFilter(request, response); |
| | | } |
| | | // é»è®¤ Request å
è£
|
| | | else if (!xssProperties.getEnabled() || isXssSkip(path)) { |
| | | BladeHttpServletRequestWrapper bladeRequest = new BladeHttpServletRequestWrapper((HttpServletRequest) request); |
| | | chain.doFilter(bladeRequest, response); |
| | | } |
| | | // Xss Request å
è£
|
| | | else { |
| | | XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); |
| | | chain.doFilter(xssRequest, response); |
| | | } |
| | | } |
| | | |
| | | private boolean isRequestSkip(String path) { |
| | | return requestProperties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path)); |
| | | } |
| | | |
| | | private boolean isXssSkip(String path) { |
| | | return xssProperties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path)); |
| | | } |
| | | |
| | | @Override |
| | | public void destroy() { |
| | | |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.request; |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Requesté
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | @ConfigurationProperties("blade.request") |
| | | public class RequestProperties { |
| | | |
| | | /** |
| | | * å¼å¯èªå®ä¹request |
| | | */ |
| | | private Boolean enabled = true; |
| | | |
| | | /** |
| | | * æ¾è¡url |
| | | */ |
| | | private List<String> skipUrl = new ArrayList<>(); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.boot.request; |
| | | |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | |
| | | import java.util.*; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ConcurrentMap; |
| | | import java.util.logging.Logger; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | /** |
| | | * HTML filtering utility for protecting against XSS (Cross Site Scripting). |
| | | * <p> |
| | | * This code is licensed LGPLv3 |
| | | * <p> |
| | | * This code is a Java port of the original work in PHP by Cal Hendersen. |
| | | * http://code.iamcal.com/php/lib_filter/ |
| | | * <p> |
| | | * The trickiest part of the translation was handling the differences in regex handling |
| | | * between PHP and Java. These resources were helpful in the process: |
| | | * <p> |
| | | * http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html |
| | | * http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php |
| | | * http://www.regular-expressions.info/modifiers.html |
| | | * <p> |
| | | * A note on naming conventions: instance variables are prefixed with a "v"; global |
| | | * constants are in all caps. |
| | | * <p> |
| | | * Sample use: |
| | | * String input = ... |
| | | * String clean = new HtmlFilter().filter( input ); |
| | | * <p> |
| | | * The class is not thread safe. Create a new instance if in doubt. |
| | | * <p> |
| | | * If you find bugs or have suggestions on improvement (especially regarding |
| | | * performance), please contact us. The latest version of this |
| | | * source, and our contact details, can be found at http://xss-html-filter.sf.net |
| | | * |
| | | * @author Joseph O'Connell |
| | | * @author Cal Hendersen |
| | | * @author Michael Semb Wever |
| | | */ |
| | | public final class XssHtmlFilter { |
| | | |
| | | /** |
| | | * regex flag union representing /si modifiers in php |
| | | **/ |
| | | private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; |
| | | private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL); |
| | | private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); |
| | | private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); |
| | | private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); |
| | | private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); |
| | | private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); |
| | | private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); |
| | | private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); |
| | | private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); |
| | | private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); |
| | | private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); |
| | | private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); |
| | | private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); |
| | | private static final Pattern P_END_ARROW = Pattern.compile("^>"); |
| | | private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); |
| | | private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); |
| | | private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); |
| | | private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); |
| | | private static final Pattern P_AMP = Pattern.compile("&"); |
| | | private static final Pattern P_QUOTE = Pattern.compile("<"); |
| | | private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); |
| | | private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); |
| | | private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); |
| | | |
| | | |
| | | private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>(); |
| | | private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>(); |
| | | |
| | | /** |
| | | * set of allowed html elements, along with allowed attributes for each element |
| | | **/ |
| | | private final Map<String, List<String>> vAllowed; |
| | | /** |
| | | * counts of open tags for each (allowable) html element |
| | | **/ |
| | | private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>(); |
| | | |
| | | /** |
| | | * html elements which must always be self-closing (e.g. "<img />") |
| | | **/ |
| | | private final String[] vSelfClosingTags; |
| | | /** |
| | | * html elements which must always have separate opening and closing tags (e.g. "<b></b>") |
| | | **/ |
| | | private final String[] vNeedClosingTags; |
| | | /** |
| | | * set of disallowed html elements |
| | | **/ |
| | | private final String[] vDisallowed; |
| | | /** |
| | | * attributes which should be checked for valid protocols |
| | | **/ |
| | | private final String[] vProtocolAtts; |
| | | /** |
| | | * allowed protocols |
| | | **/ |
| | | private final String[] vAllowedProtocols; |
| | | /** |
| | | * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") |
| | | **/ |
| | | private final String[] vRemoveBlanks; |
| | | /** |
| | | * entities allowed within html markup |
| | | **/ |
| | | private final String[] vAllowedEntities; |
| | | /** |
| | | * flag determining whether comments are allowed in input String. |
| | | */ |
| | | private final boolean stripComment; |
| | | private final boolean encodeQuotes; |
| | | private boolean vDebug = false; |
| | | /** |
| | | * flag determining whether to try to make tags when presented with "unbalanced" |
| | | * angle brackets (e.g. "<b text </b>" becomes "<b> text </b>"). If set to false, |
| | | * unbalanced angle brackets will be html escaped. |
| | | */ |
| | | private final boolean alwaysMakeTags; |
| | | |
| | | /** |
| | | * Default constructor. |
| | | */ |
| | | public XssHtmlFilter() { |
| | | vAllowed = new HashMap<>(); |
| | | |
| | | final ArrayList<String> aAtts = new ArrayList<String>(); |
| | | aAtts.add("href"); |
| | | aAtts.add("target"); |
| | | vAllowed.put("a", aAtts); |
| | | |
| | | final ArrayList<String> imgAtts = new ArrayList<String>(); |
| | | imgAtts.add("src"); |
| | | imgAtts.add("width"); |
| | | imgAtts.add("height"); |
| | | imgAtts.add("alt"); |
| | | vAllowed.put("img", imgAtts); |
| | | |
| | | final ArrayList<String> noAtts = new ArrayList<String>(); |
| | | vAllowed.put("b", noAtts); |
| | | vAllowed.put("strong", noAtts); |
| | | vAllowed.put("i", noAtts); |
| | | vAllowed.put("em", noAtts); |
| | | |
| | | vSelfClosingTags = new String[]{"img"}; |
| | | vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"}; |
| | | vDisallowed = new String[]{}; |
| | | vAllowedProtocols = new String[]{"http", "mailto", "https"}; |
| | | vProtocolAtts = new String[]{"src", "href"}; |
| | | vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"}; |
| | | vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"}; |
| | | stripComment = true; |
| | | encodeQuotes = true; |
| | | alwaysMakeTags = false; |
| | | } |
| | | |
| | | /** |
| | | * Set debug flag to true. Otherwise use default settings. See the default constructor. |
| | | * |
| | | * @param debug turn debug on with a true argument |
| | | */ |
| | | public XssHtmlFilter(final boolean debug) { |
| | | this(); |
| | | vDebug = debug; |
| | | |
| | | } |
| | | |
| | | /** |
| | | * Map-parameter configurable constructor. |
| | | * |
| | | * @param conf map containing configuration. keys match field names. |
| | | */ |
| | | public XssHtmlFilter(final Map<String, Object> conf) { |
| | | |
| | | assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; |
| | | assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; |
| | | assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; |
| | | assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; |
| | | assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; |
| | | assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; |
| | | assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; |
| | | assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; |
| | | |
| | | vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed")); |
| | | vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); |
| | | vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); |
| | | vDisallowed = (String[]) conf.get("vDisallowed"); |
| | | vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); |
| | | vProtocolAtts = (String[]) conf.get("vProtocolAtts"); |
| | | vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); |
| | | vAllowedEntities = (String[]) conf.get("vAllowedEntities"); |
| | | stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; |
| | | encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; |
| | | alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; |
| | | } |
| | | |
| | | private void reset() { |
| | | vTagCounts.clear(); |
| | | } |
| | | |
| | | private void debug(final String msg) { |
| | | if (vDebug) { |
| | | Logger.getAnonymousLogger().info(msg); |
| | | } |
| | | } |
| | | |
| | | public static String chr(final int decimal) { |
| | | return String.valueOf((char) decimal); |
| | | } |
| | | |
| | | public static String htmlSpecialChars(final String s) { |
| | | String result = s; |
| | | result = regexReplace(P_AMP, "&", result); |
| | | result = regexReplace(P_QUOTE, """, result); |
| | | result = regexReplace(P_LEFT_ARROW, "<", result); |
| | | result = regexReplace(P_RIGHT_ARROW, ">", result); |
| | | return result; |
| | | } |
| | | |
| | | //--------------------------------------------------------------- |
| | | |
| | | /** |
| | | * given a user submitted input String, filter out any invalid or restricted |
| | | * html. |
| | | * |
| | | * @param input text (i.e. submitted by a user) than may contain html |
| | | * @return "clean" version of input, with only valid, whitelisted html elements allowed |
| | | */ |
| | | public String filter(final String input) { |
| | | reset(); |
| | | String s = input; |
| | | |
| | | debug("************************************************"); |
| | | debug(" INPUT: " + input); |
| | | |
| | | s = escapeComments(s); |
| | | debug(" escapeComments: " + s); |
| | | |
| | | s = balanceHtml(s); |
| | | debug(" balanceHtml: " + s); |
| | | |
| | | s = checkTags(s); |
| | | debug(" checkTags: " + s); |
| | | |
| | | s = processRemoveBlanks(s); |
| | | debug("processRemoveBlanks: " + s); |
| | | |
| | | s = validateEntities(s); |
| | | debug(" validateEntites: " + s); |
| | | |
| | | debug("************************************************\n\n"); |
| | | return s; |
| | | } |
| | | |
| | | public boolean isAlwaysMakeTags() { |
| | | return alwaysMakeTags; |
| | | } |
| | | |
| | | public boolean isStripComments() { |
| | | return stripComment; |
| | | } |
| | | |
| | | private String escapeComments(final String s) { |
| | | final Matcher m = P_COMMENTS.matcher(s); |
| | | final StringBuffer buf = new StringBuffer(); |
| | | if (m.find()) { |
| | | final String match = m.group(1); |
| | | m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->")); |
| | | } |
| | | m.appendTail(buf); |
| | | |
| | | return buf.toString(); |
| | | } |
| | | |
| | | private String balanceHtml(String s) { |
| | | if (alwaysMakeTags) { |
| | | // |
| | | // try and form html |
| | | // |
| | | s = regexReplace(P_END_ARROW, "", s); |
| | | s = regexReplace(P_BODY_TO_END, "<$1>", s); |
| | | s = regexReplace(P_XML_CONTENT, "$1<$2", s); |
| | | |
| | | } else { |
| | | // |
| | | // escape stray brackets |
| | | // |
| | | s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); |
| | | s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); |
| | | |
| | | // |
| | | // the last regexp causes '<>' entities to appear |
| | | // (we need to do a lookahead assertion so that the last bracket can |
| | | // be used in the next pass of the regexp) |
| | | // |
| | | s = regexReplace(P_BOTH_ARROWS, "", s); |
| | | } |
| | | |
| | | return s; |
| | | } |
| | | |
| | | private String checkTags(String s) { |
| | | Matcher m = P_TAGS.matcher(s); |
| | | |
| | | final StringBuffer buf = new StringBuffer(); |
| | | while (m.find()) { |
| | | String replaceStr = m.group(1); |
| | | replaceStr = processTag(replaceStr); |
| | | m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); |
| | | } |
| | | m.appendTail(buf); |
| | | |
| | | s = buf.toString(); |
| | | |
| | | // these get tallied in processTag |
| | | // (remember to reset before subsequent calls to filter method) |
| | | for (String key : vTagCounts.keySet()) { |
| | | for (int ii = 0; ii < vTagCounts.get(key); ii++) { |
| | | s += "</" + key + ">"; |
| | | } |
| | | } |
| | | |
| | | return s; |
| | | } |
| | | |
| | | private String processRemoveBlanks(final String s) { |
| | | String result = s; |
| | | for (String tag : vRemoveBlanks) { |
| | | if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) { |
| | | P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">")); |
| | | } |
| | | result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); |
| | | if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) { |
| | | P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); |
| | | } |
| | | result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | private static String regexReplace(final Pattern regexPattern, final String replacement, final String s) { |
| | | Matcher m = regexPattern.matcher(s); |
| | | return m.replaceAll(replacement); |
| | | } |
| | | |
| | | private String processTag(final String s) { |
| | | Matcher m = P_END_TAG.matcher(s); |
| | | if (m.find()) { |
| | | final String name = m.group(1).toLowerCase(); |
| | | if (allowed(name)) { |
| | | if (!inArray(name, vSelfClosingTags)) { |
| | | if (vTagCounts.containsKey(name)) { |
| | | vTagCounts.put(name, vTagCounts.get(name) - 1); |
| | | return "</" + name + ">"; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | m = P_START_TAG.matcher(s); |
| | | if (m.find()) { |
| | | final String name = m.group(1).toLowerCase(); |
| | | final String body = m.group(2); |
| | | String ending = m.group(3); |
| | | if (allowed(name)) { |
| | | String params = ""; |
| | | final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); |
| | | final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); |
| | | final List<String> paramNames = new ArrayList<String>(); |
| | | final List<String> paramValues = new ArrayList<String>(); |
| | | while (m2.find()) { |
| | | paramNames.add(m2.group(1)); |
| | | paramValues.add(m2.group(3)); |
| | | } |
| | | while (m3.find()) { |
| | | paramNames.add(m3.group(1)); |
| | | paramValues.add(m3.group(3)); |
| | | } |
| | | String paramName, paramValue; |
| | | for (int ii = 0; ii < paramNames.size(); ii++) { |
| | | paramName = paramNames.get(ii).toLowerCase(); |
| | | paramValue = paramValues.get(ii); |
| | | if (allowedAttribute(name, paramName)) { |
| | | if (inArray(paramName, vProtocolAtts)) { |
| | | paramValue = processParamProtocol(paramValue); |
| | | } |
| | | params += " " + paramName + "=\"" + paramValue + "\""; |
| | | } |
| | | } |
| | | if (inArray(name, vSelfClosingTags)) { |
| | | ending = " /"; |
| | | } |
| | | if (inArray(name, vNeedClosingTags)) { |
| | | ending = ""; |
| | | } |
| | | if (ending == null || ending.length() < 1) { |
| | | if (vTagCounts.containsKey(name)) { |
| | | vTagCounts.put(name, vTagCounts.get(name) + 1); |
| | | } else { |
| | | vTagCounts.put(name, 1); |
| | | } |
| | | } else { |
| | | ending = " /"; |
| | | } |
| | | return "<" + name + params + ending + ">"; |
| | | } else { |
| | | return ""; |
| | | } |
| | | } |
| | | m = P_COMMENT.matcher(s); |
| | | if (!stripComment && m.find()) { |
| | | return "<" + m.group() + ">"; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | private String processParamProtocol(String s) { |
| | | s = decodeEntities(s); |
| | | final Matcher m = P_PROTOCOL.matcher(s); |
| | | if (m.find()) { |
| | | final String protocol = m.group(1); |
| | | if (!inArray(protocol, vAllowedProtocols)) { |
| | | // bad protocol, turn into local anchor link instead |
| | | s = "#" + s.substring(protocol.length() + 1); |
| | | if (s.startsWith(StringPool.DOUBLE_SLASH)) { |
| | | s = "#" + s.substring(3); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return s; |
| | | } |
| | | |
| | | private String decodeEntities(String s) { |
| | | StringBuffer buf = new StringBuffer(); |
| | | |
| | | Matcher m = P_ENTITY.matcher(s); |
| | | while (m.find()) { |
| | | final String match = m.group(1); |
| | | final int decimal = Integer.decode(match); |
| | | m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
| | | } |
| | | m.appendTail(buf); |
| | | s = buf.toString(); |
| | | |
| | | buf = new StringBuffer(); |
| | | m = P_ENTITY_UNICODE.matcher(s); |
| | | while (m.find()) { |
| | | final String match = m.group(1); |
| | | final int decimal = Integer.valueOf(match, 16).intValue(); |
| | | m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
| | | } |
| | | m.appendTail(buf); |
| | | s = buf.toString(); |
| | | |
| | | buf = new StringBuffer(); |
| | | m = P_ENCODE.matcher(s); |
| | | while (m.find()) { |
| | | final String match = m.group(1); |
| | | final int decimal = Integer.valueOf(match, 16).intValue(); |
| | | m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); |
| | | } |
| | | m.appendTail(buf); |
| | | s = buf.toString(); |
| | | |
| | | s = validateEntities(s); |
| | | return s; |
| | | } |
| | | |
| | | private String validateEntities(final String s) { |
| | | StringBuffer buf = new StringBuffer(); |
| | | |
| | | // validate entities throughout the string |
| | | Matcher m = P_VALID_ENTITIES.matcher(s); |
| | | while (m.find()) { |
| | | final String one = m.group(1); |
| | | final String two = m.group(2); |
| | | m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); |
| | | } |
| | | m.appendTail(buf); |
| | | |
| | | return encodeQuotes(buf.toString()); |
| | | } |
| | | |
| | | private String encodeQuotes(final String s) { |
| | | if (encodeQuotes) { |
| | | StringBuffer buf = new StringBuffer(); |
| | | Matcher m = P_VALID_QUOTES.matcher(s); |
| | | while (m.find()) { |
| | | final String one = m.group(1); |
| | | final String two = m.group(2); |
| | | final String three = m.group(3); |
| | | m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, """, two) + three)); |
| | | } |
| | | m.appendTail(buf); |
| | | return buf.toString(); |
| | | } else { |
| | | return s; |
| | | } |
| | | } |
| | | |
| | | private String checkEntity(final String preamble, final String term) { |
| | | |
| | | return ";".equals(term) && isValidEntity(preamble) |
| | | ? '&' + preamble |
| | | : "&" + preamble; |
| | | } |
| | | |
| | | private boolean isValidEntity(final String entity) { |
| | | return inArray(entity, vAllowedEntities); |
| | | } |
| | | |
| | | private static boolean inArray(final String s, final String[] array) { |
| | | for (String item : array) { |
| | | if (item != null && item.equals(s)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private boolean allowed(final String name) { |
| | | return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); |
| | | } |
| | | |
| | | private boolean allowedAttribute(final String name, final String paramName) { |
| | | return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.request; |
| | | |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.MediaType; |
| | | |
| | | import javax.servlet.ReadListener; |
| | | import javax.servlet.ServletInputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletRequestWrapper; |
| | | import java.io.BufferedReader; |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStreamReader; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * XSSè¿æ»¤ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { |
| | | |
| | | /** |
| | | * 没被å
è£
è¿çHttpServletRequestï¼ç¹æ®åºæ¯,éè¦èªå·±è¿æ»¤ï¼ |
| | | */ |
| | | private final HttpServletRequest orgRequest; |
| | | /** |
| | | * ç¼åæ¥æ,æ¯æå¤æ¬¡è¯»åæµ |
| | | */ |
| | | private byte[] body; |
| | | /** |
| | | * htmlè¿æ»¤ |
| | | */ |
| | | private final static XssHtmlFilter HTML_FILTER = new XssHtmlFilter(); |
| | | |
| | | public XssHttpServletRequestWrapper(HttpServletRequest request) { |
| | | super(request); |
| | | orgRequest = request; |
| | | } |
| | | |
| | | @Override |
| | | public BufferedReader getReader() throws IOException { |
| | | return new BufferedReader(new InputStreamReader(getInputStream())); |
| | | } |
| | | |
| | | @Override |
| | | public ServletInputStream getInputStream() throws IOException { |
| | | if (super.getHeader(HttpHeaders.CONTENT_TYPE) == null) { |
| | | return super.getInputStream(); |
| | | } |
| | | |
| | | if (super.getHeader(HttpHeaders.CONTENT_TYPE).startsWith(MediaType.MULTIPART_FORM_DATA_VALUE)) { |
| | | return super.getInputStream(); |
| | | } |
| | | |
| | | if (body == null) { |
| | | body = xssEncode(WebUtil.getRequestBody(super.getInputStream())).getBytes(); |
| | | } |
| | | |
| | | final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body); |
| | | |
| | | return new ServletInputStream() { |
| | | |
| | | @Override |
| | | public int read() { |
| | | return byteArrayInputStream.read(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isFinished() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isReady() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public void setReadListener(ReadListener readListener) { |
| | | } |
| | | }; |
| | | } |
| | | |
| | | @Override |
| | | public String getParameter(String name) { |
| | | String value = super.getParameter(xssEncode(name)); |
| | | if (StringUtil.isNotBlank(value)) { |
| | | value = xssEncode(value); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | @Override |
| | | public String[] getParameterValues(String name) { |
| | | String[] parameters = super.getParameterValues(name); |
| | | if (parameters == null || parameters.length == 0) { |
| | | return null; |
| | | } |
| | | |
| | | for (int i = 0; i < parameters.length; i++) { |
| | | parameters[i] = xssEncode(parameters[i]); |
| | | } |
| | | return parameters; |
| | | } |
| | | |
| | | @Override |
| | | public Map<String, String[]> getParameterMap() { |
| | | Map<String, String[]> map = new LinkedHashMap<>(); |
| | | Map<String, String[]> parameters = super.getParameterMap(); |
| | | for (String key : parameters.keySet()) { |
| | | String[] values = parameters.get(key); |
| | | for (int i = 0; i < values.length; i++) { |
| | | values[i] = xssEncode(values[i]); |
| | | } |
| | | map.put(key, values); |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | @Override |
| | | public String getHeader(String name) { |
| | | String value = super.getHeader(xssEncode(name)); |
| | | if (StringUtil.isNotBlank(value)) { |
| | | value = xssEncode(value); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | private String xssEncode(String input) { |
| | | return HTML_FILTER.filter(input); |
| | | } |
| | | |
| | | /** |
| | | * è·ååå§request |
| | | * |
| | | * @return HttpServletRequest |
| | | */ |
| | | public HttpServletRequest getOrgRequest() { |
| | | return orgRequest; |
| | | } |
| | | |
| | | /** |
| | | * è·ååå§request |
| | | * |
| | | * @param request request |
| | | * @return HttpServletRequest |
| | | */ |
| | | public static HttpServletRequest getOrgRequest(HttpServletRequest request) { |
| | | if (request instanceof XssHttpServletRequestWrapper) { |
| | | return ((XssHttpServletRequestWrapper) request).getOrgRequest(); |
| | | } |
| | | return request; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.request; |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Xssé
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | @ConfigurationProperties("blade.xss") |
| | | public class XssProperties { |
| | | |
| | | /** |
| | | * å¼å¯xss |
| | | */ |
| | | private Boolean enabled = true; |
| | | |
| | | /** |
| | | * æ¾è¡url |
| | | */ |
| | | private List<String> skipUrl = new ArrayList<>(); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.boot.resolver; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.secure.BladeUser; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springframework.core.MethodParameter; |
| | | import org.springframework.web.bind.support.WebDataBinderFactory; |
| | | import org.springframework.web.context.request.NativeWebRequest; |
| | | import org.springframework.web.method.support.HandlerMethodArgumentResolver; |
| | | import org.springframework.web.method.support.ModelAndViewContainer; |
| | | |
| | | /** |
| | | * Token转åBladeUser |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | public class TokenArgumentResolver implements HandlerMethodArgumentResolver { |
| | | |
| | | /** |
| | | * å
¥åçé |
| | | * |
| | | * @param methodParameter åæ°éå |
| | | * @return æ ¼å¼ååçåæ° |
| | | */ |
| | | @Override |
| | | public boolean supportsParameter(MethodParameter methodParameter) { |
| | | return methodParameter.getParameterType().equals(BladeUser.class); |
| | | } |
| | | |
| | | /** |
| | | * åºå设置 |
| | | * |
| | | * @param methodParameter å
¥åéå |
| | | * @param modelAndViewContainer model å view |
| | | * @param nativeWebRequest webç¸å
³ |
| | | * @param webDataBinderFactory å
¥åè§£æ |
| | | * @return å
è£
对象 |
| | | */ |
| | | @Override |
| | | public Object resolveArgument(MethodParameter methodParameter, |
| | | ModelAndViewContainer modelAndViewContainer, |
| | | NativeWebRequest nativeWebRequest, |
| | | WebDataBinderFactory webDataBinderFactory) { |
| | | return AuthUtil.getUser(); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | ${AnsiColor.BLUE} ______ _ _ ___ ___ |
| | | ${AnsiColor.BLUE} | ___ \| | | | \ \ / / |
| | | ${AnsiColor.BLUE} | |_/ /| | __ _ __| | ___ \ V / |
| | | ${AnsiColor.BLUE} | ___ \| | / _` | / _` | / _ \ > < |
| | | ${AnsiColor.BLUE} | |_/ /| || (_| || (_| || __/ / . \ |
| | | ${AnsiColor.BLUE} \____/ |_| \__,_| \__,_| \___|/__/ \__\ |
| | | |
| | | ${AnsiColor.BLUE}:: BladeX ${blade.service.version} :: ${spring.application.name}:${AnsiColor.RED}${blade.env}${AnsiColor.BLUE} :: Running SpringBoot ${spring-boot.version} :: ${AnsiColor.BRIGHT_BLACK} |
¶Ô±ÈÐÂÎļþ |
| | |
| | | #æå¡å¨é
ç½® |
| | | server: |
| | | undertow: |
| | | # 线ç¨é
ç½® |
| | | threads: |
| | | # 设置IOçº¿ç¨æ°, å®ä¸»è¦æ§è¡éé»å¡çä»»å¡,å®ä»¬ä¼è´è´£å¤ä¸ªè¿æ¥, é»è®¤è®¾ç½®æ¯ä¸ªCPUæ ¸å¿ä¸ä¸ªçº¿ç¨ |
| | | io: 16 |
| | | # é»å¡ä»»å¡çº¿ç¨æ± , 彿§è¡ç±»ä¼¼servlet请æ±é»å¡æä½, undertowä¼ä»è¿ä¸ªçº¿ç¨æ± ä¸åå¾çº¿ç¨,å®çå¼è®¾ç½®åå³äºç³»ç»çè´è½½ |
| | | worker: 400 |
| | | # 以ä¸çé
ç½®ä¼å½±åbuffer,è¿äºbufferä¼ç¨äºæå¡å¨è¿æ¥çIOæä½,æç¹ç±»ä¼¼nettyçæ± åå
å管ç |
| | | buffer-size: 1024 |
| | | # æ¯å¦åé
çç´æ¥å
å |
| | | direct-buffers: true |
| | | servlet: |
| | | # ç¼ç é
ç½® |
| | | encoding: |
| | | charset: UTF-8 |
| | | force: true |
| | | |
| | | #springé
ç½® |
| | | spring: |
| | | servlet: |
| | | multipart: |
| | | enabled: true |
| | | max-file-size: 1024MB |
| | | max-request-size: 1024MB |
| | | mvc: |
| | | throw-exception-if-no-handler-found: true |
| | | web: |
| | | resources: |
| | | add-mappings: false |
| | | devtools: |
| | | restart: |
| | | log-condition-evaluation-delta: false |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <groupId>org.springblade</groupId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-cloud</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | |
| | | <dependencies> |
| | | <!-- Blade --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-launch</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-context</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-auth</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-loadbalancer</artifactId> |
| | | </dependency> |
| | | <!-- Admin --> |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-client</artifactId> |
| | | </dependency> |
| | | <!-- Sentinel --> |
| | | <dependency> |
| | | <groupId>com.alibaba.cloud</groupId> |
| | | <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> |
| | | </dependency> |
| | | <!-- Auto --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.annotation; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * header çæ¬ å¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Target({ElementType.METHOD, ElementType.TYPE}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | @Inherited |
| | | public @interface ApiVersion { |
| | | |
| | | /** |
| | | * header è·¯å¾ä¸ççæ¬ |
| | | * |
| | | * @return çæ¬å· |
| | | */ |
| | | String value() default ""; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.annotation; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * 注解ç¨äºçæ requestMappingInfo æ¶åç´æ¥æ¼æ¥è·¯å¾è§åï¼èªå¨æ¾ç½®äºæ¹æ³è·¯å¾å¼å§é¨å |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Target({ElementType.METHOD, ElementType.TYPE}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | @Inherited |
| | | public @interface UrlVersion { |
| | | |
| | | /** |
| | | * url è·¯å¾ä¸ççæ¬ |
| | | * |
| | | * @return çæ¬å· |
| | | */ |
| | | String value() default ""; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.annotation; |
| | | |
| | | import org.springframework.core.annotation.AliasFor; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * çæ¬å·å¤ç |
| | | * |
| | | * <p> |
| | | * 1. url çæ¬å·ï¼æ·»å å° url å |
| | | * 2. Accept çæ¬ï¼application/vnd.blade.VERSION+json |
| | | * </p> |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Target(ElementType.TYPE) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | @RequestMapping |
| | | @UrlVersion |
| | | @ApiVersion |
| | | @Validated |
| | | public @interface VersionMapping { |
| | | /** |
| | | * Alias for {@link RequestMapping#name}. |
| | | * @return {String[]} |
| | | */ |
| | | @AliasFor(annotation = RequestMapping.class) |
| | | String name() default ""; |
| | | |
| | | /** |
| | | * Alias for {@link RequestMapping#value}. |
| | | * @return {String[]} |
| | | */ |
| | | @AliasFor(annotation = RequestMapping.class) |
| | | String[] value() default {}; |
| | | |
| | | /** |
| | | * Alias for {@link RequestMapping#path}. |
| | | * @return {String[]} |
| | | */ |
| | | @AliasFor(annotation = RequestMapping.class) |
| | | String[] path() default {}; |
| | | |
| | | /** |
| | | * Alias for {@link RequestMapping#params}. |
| | | * @return {String[]} |
| | | */ |
| | | @AliasFor(annotation = RequestMapping.class) |
| | | String[] params() default {}; |
| | | |
| | | /** |
| | | * Alias for {@link RequestMapping#headers}. |
| | | * @return {String[]} |
| | | */ |
| | | @AliasFor(annotation = RequestMapping.class) |
| | | String[] headers() default {}; |
| | | |
| | | /** |
| | | * Alias for {@link RequestMapping#consumes}. |
| | | * @return {String[]} |
| | | */ |
| | | @AliasFor(annotation = RequestMapping.class) |
| | | String[] consumes() default {}; |
| | | |
| | | /** |
| | | * Alias for {@link RequestMapping#produces}. |
| | | * default json utf-8 |
| | | * @return {String[]} |
| | | */ |
| | | @AliasFor(annotation = RequestMapping.class) |
| | | String[] produces() default {}; |
| | | |
| | | /** |
| | | * Alias for {@link UrlVersion#value}. |
| | | * @return {String} |
| | | */ |
| | | @AliasFor(annotation = UrlVersion.class, attribute = "value") |
| | | String urlVersion() default ""; |
| | | |
| | | /** |
| | | * Alias for {@link ApiVersion#value}. |
| | | * @return {String} |
| | | */ |
| | | @AliasFor(annotation = ApiVersion.class, attribute = "value") |
| | | String apiVersion() default ""; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.cloud.client; |
| | | |
| | | import org.springblade.core.launch.constant.AppConstant; |
| | | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| | | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; |
| | | import org.springframework.cloud.openfeign.EnableFeignClients; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * Cloudå¯å¨æ³¨è§£é
ç½® |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Target(ElementType.TYPE) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | @Inherited |
| | | @EnableDiscoveryClient |
| | | @EnableFeignClients(AppConstant.BASE_PACKAGES) |
| | | @SpringBootApplication |
| | | public @interface BladeCloudApplication { |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.feign; |
| | | |
| | | import feign.Target; |
| | | import org.springframework.cloud.openfeign.FallbackFactory; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.cglib.proxy.Enhancer; |
| | | |
| | | /** |
| | | * é»è®¤ Fallbackï¼é¿å
åè¿å¤fallbackç±» |
| | | * |
| | | * @param <T> æ³åæ è®° |
| | | * @author L.cm |
| | | */ |
| | | @AllArgsConstructor |
| | | public class BladeFallbackFactory<T> implements FallbackFactory<T> { |
| | | private final Target<T> target; |
| | | |
| | | @Override |
| | | @SuppressWarnings("unchecked") |
| | | public T create(Throwable cause) { |
| | | final Class<T> targetType = target.type(); |
| | | final String targetName = target.name(); |
| | | Enhancer enhancer = new Enhancer(); |
| | | enhancer.setSuperclass(targetType); |
| | | enhancer.setUseCache(true); |
| | | enhancer.setCallback(new BladeFeignFallback<>(targetType, targetName, cause)); |
| | | return (T) enhancer.create(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.feign; |
| | | |
| | | import com.fasterxml.jackson.databind.JsonNode; |
| | | import feign.FeignException; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.api.ResultCode; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springblade.core.tool.utils.ObjectUtil; |
| | | import org.springframework.cglib.proxy.MethodInterceptor; |
| | | import org.springframework.cglib.proxy.MethodProxy; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * blade fallBack 代çå¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | @AllArgsConstructor |
| | | public class BladeFeignFallback<T> implements MethodInterceptor { |
| | | private final Class<T> targetType; |
| | | private final String targetName; |
| | | private final Throwable cause; |
| | | private final static String CODE = "code"; |
| | | |
| | | @Nullable |
| | | @Override |
| | | public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { |
| | | String errorMessage = cause.getMessage(); |
| | | log.error("BladeFeignFallback:[{}.{}] serviceId:[{}] message:[{}]", targetType.getName(), method.getName(), targetName, errorMessage); |
| | | Class<?> returnType = method.getReturnType(); |
| | | // éåç±»ååé¦ç©ºéå |
| | | if (List.class == returnType || Collection.class == returnType) { |
| | | return Collections.emptyList(); |
| | | } |
| | | if (Set.class == returnType) { |
| | | return Collections.emptySet(); |
| | | } |
| | | if (Map.class == returnType) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | // ææ¶ä¸æ¯æ fluxï¼rxï¼å¼æ¥çï¼è¿åå¼ä¸æ¯ Rï¼ç´æ¥è¿å nullã |
| | | if (R.class != returnType) { |
| | | return null; |
| | | } |
| | | // é FeignException |
| | | if (!(cause instanceof FeignException)) { |
| | | return R.fail(ResultCode.INTERNAL_SERVER_ERROR, errorMessage); |
| | | } |
| | | FeignException exception = (FeignException) cause; |
| | | byte[] content = exception.content(); |
| | | // 妿è¿åçæ°æ®ä¸ºç©º |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return R.fail(ResultCode.INTERNAL_SERVER_ERROR, errorMessage); |
| | | } |
| | | // è½¬æ¢æ jsonNode 读åï¼å ä¸ºç´æ¥è½¬æ¢ï¼å¯è½ å¯¹æ¹æ¾åçå¹¶ 䏿¯ R çæ ¼å¼ã |
| | | JsonNode resultNode = JsonUtil.readTree(content); |
| | | // 夿æ¯å¦ R æ ¼å¼ è¿åä½ |
| | | if (resultNode.has(CODE)) { |
| | | return JsonUtil.getInstance().convertValue(resultNode, R.class); |
| | | } |
| | | return R.fail(resultNode.toString()); |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(Object o) { |
| | | if (this == o) { |
| | | return true; |
| | | } |
| | | if (o == null || getClass() != o.getClass()) { |
| | | return false; |
| | | } |
| | | BladeFeignFallback<?> that = (BladeFeignFallback<?>) o; |
| | | return targetType.equals(that.targetType); |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return Objects.hash(targetType); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.feign; |
| | | |
| | | import feign.RequestInterceptor; |
| | | import feign.RequestTemplate; |
| | | import org.springblade.core.tool.constant.BladeConstant; |
| | | import org.springblade.core.tool.utils.ThreadLocalUtil; |
| | | import org.springframework.http.HttpHeaders; |
| | | |
| | | /** |
| | | * feign ä¼ éRequest header |
| | | * |
| | | * <p> |
| | | * https://blog.csdn.net/u014519194/article/details/77160958 |
| | | * http://tietang.wang/2016/02/25/hystrix/Hystrix%E5%8F%82%E6%95%B0%E8%AF%A6%E8%A7%A3/ |
| | | * https://github.com/Netflix/Hystrix/issues/92#issuecomment-260548068 |
| | | * </p> |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeFeignRequestInterceptor implements RequestInterceptor { |
| | | |
| | | @Override |
| | | public void apply(RequestTemplate requestTemplate) { |
| | | HttpHeaders headers = ThreadLocalUtil.get(BladeConstant.CONTEXT_KEY); |
| | | if (headers != null && !headers.isEmpty()) { |
| | | headers.forEach((key, values) -> |
| | | values.forEach(value -> requestTemplate.header(key, value)) |
| | | ); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | |
| | | package org.springblade.core.cloud.feign; |
| | | |
| | | |
| | | import org.springblade.core.launch.constant.AppConstant; |
| | | import org.springframework.cloud.openfeign.EnableFeignClients; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * å¼å¯Feign注解 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Documented |
| | | @Target(ElementType.TYPE) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @EnableFeignClients(AppConstant.BASE_PACKAGES) |
| | | public @interface EnableBladeFeign { |
| | | /** |
| | | * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation |
| | | * declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of |
| | | * {@code @ComponentScan(basePackages="org.my.pkg")}. |
| | | * |
| | | * @return the array of 'basePackages'. |
| | | */ |
| | | String[] value() default {}; |
| | | |
| | | /** |
| | | * Base packages to scan for annotated components. |
| | | * <p> |
| | | * {@link #value()} is an alias for (and mutually exclusive with) this attribute. |
| | | * <p> |
| | | * Use {@link #basePackageClasses()} for a type-safe alternative to String-based |
| | | * package names. |
| | | * |
| | | * @return the array of 'basePackages'. |
| | | */ |
| | | String[] basePackages() default {}; |
| | | |
| | | /** |
| | | * Type-safe alternative to {@link #basePackages()} for specifying the packages to |
| | | * scan for annotated components. The package of each class specified will be scanned. |
| | | * <p> |
| | | * Consider creating a special no-op marker class or interface in each package that |
| | | * serves no purpose other than being referenced by this attribute. |
| | | * |
| | | * @return the array of 'basePackageClasses'. |
| | | */ |
| | | Class<?>[] basePackageClasses() default {}; |
| | | |
| | | /** |
| | | * A custom <code>@Configuration</code> for all feign clients. Can contain override |
| | | * <code>@Bean</code> definition for the pieces that make up the client, for instance |
| | | * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}. |
| | | */ |
| | | Class<?>[] defaultConfiguration() default {}; |
| | | |
| | | /** |
| | | * List of classes annotated with @FeignClient. If not empty, disables classpath scanning. |
| | | * |
| | | * @return |
| | | */ |
| | | Class<?>[] clients() default {}; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.http; |
| | | |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | |
| | | /** |
| | | * http é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoConfiguration |
| | | @EnableConfigurationProperties(BladeHttpProperties.class) |
| | | public class BladeHttpConfiguration { |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.http; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import org.springblade.core.launch.log.BladeLogLevel; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.cloud.context.config.annotation.RefreshScope; |
| | | |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * http é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @RefreshScope |
| | | @ConfigurationProperties("blade.http") |
| | | public class BladeHttpProperties { |
| | | /** |
| | | * æå¤§è¿æ¥æ°ï¼é»è®¤ï¼200 |
| | | */ |
| | | private int maxConnections = 200; |
| | | /** |
| | | * è¿æ¥åæ´»æ¶é´ï¼é»è®¤ï¼900L |
| | | */ |
| | | private long timeToLive = 900L; |
| | | /** |
| | | * è¿æ¥æ± åæ´»æ¶é´åä½ï¼é»è®¤ï¼ç§ |
| | | */ |
| | | private TimeUnit timeUnit = TimeUnit.SECONDS; |
| | | /** |
| | | * 龿¥è¶
æ¶ï¼é»è®¤ï¼2000æ¯«ç§ |
| | | */ |
| | | private int connectionTimeout = 2000; |
| | | /** |
| | | * æ¯å¦æ¯æéå®åï¼é»è®¤ï¼true |
| | | */ |
| | | private boolean followRedirects = true; |
| | | /** |
| | | * å
³éè¯ä¹¦æ ¡éª |
| | | */ |
| | | private boolean disableSslValidation = true; |
| | | /** |
| | | * æ¥å¿çº§å« |
| | | */ |
| | | private BladeLogLevel level = BladeLogLevel.NONE; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.cloud.http; |
| | | |
| | | import org.springframework.http.client.ClientHttpRequestFactory; |
| | | import org.springframework.http.converter.HttpMessageConverter; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Loadbalancer RestTemplate |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class LbRestTemplate extends RestTemplate { |
| | | |
| | | public LbRestTemplate() { |
| | | super(); |
| | | } |
| | | |
| | | public LbRestTemplate(ClientHttpRequestFactory requestFactory) { |
| | | super(requestFactory); |
| | | } |
| | | |
| | | public LbRestTemplate(List<HttpMessageConverter<?>> messageConverters) { |
| | | super(messageConverters); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.http; |
| | | |
| | | |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.ConnectionPool; |
| | | import okhttp3.OkHttpClient; |
| | | import org.springblade.core.cloud.http.logger.HttpLoggingInterceptor; |
| | | import org.springblade.core.cloud.http.logger.OkHttpSlf4jLogger; |
| | | import org.springblade.core.tool.ssl.DisableValidationTrustManager; |
| | | import org.springblade.core.tool.ssl.TrustAllHostNames; |
| | | import org.springblade.core.tool.utils.Charsets; |
| | | import org.springblade.core.tool.utils.Holder; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.web.client.RestTemplateBuilder; |
| | | import org.springframework.cloud.client.loadbalancer.LoadBalanced; |
| | | import org.springframework.context.ApplicationContext; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; |
| | | import org.springframework.http.converter.HttpMessageConverter; |
| | | import org.springframework.http.converter.StringHttpMessageConverter; |
| | | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | | import javax.net.ssl.SSLSocketFactory; |
| | | import javax.net.ssl.TrustManager; |
| | | import javax.net.ssl.X509TrustManager; |
| | | import java.security.KeyManagementException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.util.List; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * Http RestTemplateHeaderInterceptor é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @AutoConfiguration |
| | | @ConditionalOnClass(OkHttpClient.class) |
| | | @ConditionalOnProperty(value = "blade.http.enabled", matchIfMissing = true) |
| | | public class RestTemplateConfiguration { |
| | | private final BladeHttpProperties properties; |
| | | |
| | | /** |
| | | * okhttp3 è¯·æ±æ¥å¿æ¦æªå¨ |
| | | * |
| | | * @return HttpLoggingInterceptor |
| | | */ |
| | | @Bean |
| | | public HttpLoggingInterceptor loggingInterceptor() { |
| | | HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new OkHttpSlf4jLogger()); |
| | | interceptor.setLevel(properties.getLevel()); |
| | | return interceptor; |
| | | } |
| | | |
| | | /** |
| | | * okhttp3 龿¥æ± é
ç½® |
| | | * |
| | | * @return okhttp3.ConnectionPool |
| | | */ |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public ConnectionPool httpClientConnectionPool() { |
| | | int maxTotalConnections = properties.getMaxConnections(); |
| | | long timeToLive = properties.getTimeToLive(); |
| | | TimeUnit ttlUnit = properties.getTimeUnit(); |
| | | return new ConnectionPool(maxTotalConnections, timeToLive, ttlUnit); |
| | | } |
| | | |
| | | /** |
| | | * é
ç½®OkHttpClient |
| | | * |
| | | * @param connectionPool 龿¥æ± é
ç½® |
| | | * @param interceptor æ¦æªå¨ |
| | | * @return OkHttpClient |
| | | */ |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public OkHttpClient okHttpClient(ConnectionPool connectionPool, HttpLoggingInterceptor interceptor) { |
| | | boolean followRedirects = properties.isFollowRedirects(); |
| | | int connectTimeout = properties.getConnectionTimeout(); |
| | | return this.createBuilder(properties.isDisableSslValidation()) |
| | | .connectTimeout(connectTimeout, TimeUnit.MILLISECONDS) |
| | | .writeTimeout(30, TimeUnit.SECONDS) |
| | | .readTimeout(30, TimeUnit.SECONDS) |
| | | .followRedirects(followRedirects) |
| | | .connectionPool(connectionPool) |
| | | .addInterceptor(interceptor) |
| | | .build(); |
| | | } |
| | | |
| | | private OkHttpClient.Builder createBuilder(boolean disableSslValidation) { |
| | | OkHttpClient.Builder builder = new OkHttpClient.Builder(); |
| | | if (disableSslValidation) { |
| | | try { |
| | | X509TrustManager disabledTrustManager = DisableValidationTrustManager.INSTANCE; |
| | | TrustManager[] trustManagers = new TrustManager[]{disabledTrustManager}; |
| | | SSLContext sslContext = SSLContext.getInstance("SSL"); |
| | | sslContext.init(null, trustManagers, Holder.SECURE_RANDOM); |
| | | SSLSocketFactory disabledSslSocketFactory = sslContext.getSocketFactory(); |
| | | builder.sslSocketFactory(disabledSslSocketFactory, disabledTrustManager); |
| | | builder.hostnameVerifier(TrustAllHostNames.INSTANCE); |
| | | } catch (NoSuchAlgorithmException | KeyManagementException e) { |
| | | log.warn("Error setting SSLSocketFactory in OKHttpClient", e); |
| | | } |
| | | } |
| | | return builder; |
| | | } |
| | | |
| | | @Bean |
| | | public RestTemplateHeaderInterceptor requestHeaderInterceptor() { |
| | | return new RestTemplateHeaderInterceptor(); |
| | | } |
| | | |
| | | @AutoConfiguration |
| | | @RequiredArgsConstructor |
| | | @ConditionalOnClass(OkHttpClient.class) |
| | | @ConditionalOnProperty(value = "blade.http.rest-template.enable") |
| | | public static class RestTemplateAutoConfiguration { |
| | | private final ApplicationContext context; |
| | | |
| | | /** |
| | | * æ®éç RestTemplateï¼ä¸éä¼ è¯·æ±å¤´ï¼ä¸è¬åªåå¤é¨ http è°ç¨ |
| | | * |
| | | * @param okHttpClient OkHttpClient |
| | | * @return RestTemplate |
| | | */ |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder, OkHttpClient okHttpClient) { |
| | | restTemplateBuilder.requestFactory(() -> new OkHttp3ClientHttpRequestFactory(okHttpClient)); |
| | | RestTemplate restTemplate = restTemplateBuilder.build(); |
| | | configMessageConverters(context, restTemplate.getMessageConverters()); |
| | | return restTemplate; |
| | | } |
| | | } |
| | | |
| | | @AutoConfiguration |
| | | @RequiredArgsConstructor |
| | | @ConditionalOnClass(OkHttpClient.class) |
| | | @ConditionalOnProperty(value = "blade.http.lb-rest-template.enable") |
| | | public static class LbRestTemplateAutoConfiguration { |
| | | private final ApplicationContext context; |
| | | |
| | | /** |
| | | * æ¯æè´è½½åè¡¡ç LbRestTemplate |
| | | * |
| | | * @param okHttpClient OkHttpClient |
| | | * @return LbRestTemplate |
| | | */ |
| | | @Bean |
| | | @LoadBalanced |
| | | @ConditionalOnMissingBean |
| | | public LbRestTemplate lbRestTemplate(RestTemplateBuilder restTemplateBuilder, OkHttpClient okHttpClient) { |
| | | restTemplateBuilder.requestFactory(() -> new OkHttp3ClientHttpRequestFactory(okHttpClient)); |
| | | LbRestTemplate restTemplate = restTemplateBuilder.build(LbRestTemplate.class); |
| | | restTemplate.getInterceptors().add(context.getBean(RestTemplateHeaderInterceptor.class)); |
| | | configMessageConverters(context, restTemplate.getMessageConverters()); |
| | | return restTemplate; |
| | | } |
| | | } |
| | | |
| | | private static void configMessageConverters(ApplicationContext context, List<HttpMessageConverter<?>> converters) { |
| | | converters.removeIf(x -> x instanceof StringHttpMessageConverter || x instanceof MappingJackson2HttpMessageConverter); |
| | | converters.add(new StringHttpMessageConverter(Charsets.UTF_8)); |
| | | converters.add(new MappingJackson2HttpMessageConverter(context.getBean(ObjectMapper.class))); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.http; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springblade.core.tool.constant.BladeConstant; |
| | | import org.springblade.core.tool.utils.ThreadLocalUtil; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.HttpRequest; |
| | | import org.springframework.http.client.ClientHttpRequestExecution; |
| | | import org.springframework.http.client.ClientHttpRequestInterceptor; |
| | | import org.springframework.http.client.ClientHttpResponse; |
| | | import org.springframework.lang.NonNull; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * RestTemplateHeaderInterceptor ä¼ éRequest header |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AllArgsConstructor |
| | | public class RestTemplateHeaderInterceptor implements ClientHttpRequestInterceptor { |
| | | @NonNull |
| | | @Override |
| | | public ClientHttpResponse intercept(@NonNull HttpRequest request, @NonNull byte[] bytes, @NonNull ClientHttpRequestExecution execution) throws IOException { |
| | | HttpHeaders headers = ThreadLocalUtil.get(BladeConstant.CONTEXT_KEY); |
| | | if (headers != null && !headers.isEmpty()) { |
| | | HttpHeaders httpHeaders = request.getHeaders(); |
| | | headers.forEach((key, values) -> values.forEach(value -> httpHeaders.add(key, value))); |
| | | } |
| | | return execution.execute(request, bytes); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.cloud.http.logger; |
| | | |
| | | import okhttp3.*; |
| | | import okhttp3.internal.http.HttpHeaders; |
| | | import okio.Buffer; |
| | | import okio.BufferedSource; |
| | | import okio.GzipSource; |
| | | import org.springblade.core.launch.log.BladeLogLevel; |
| | | |
| | | import java.io.EOFException; |
| | | import java.io.IOException; |
| | | import java.nio.charset.Charset; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.Objects; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * An OkHttp interceptor which logs request and response information. Can be applied as an |
| | | * {@linkplain OkHttpClient#interceptors() application interceptor} or as a {@linkplain |
| | | * OkHttpClient#networkInterceptors() network interceptor}. <p> The format of the logs created by |
| | | * this class should not be considered stable and may change slightly between releases. If you need |
| | | * a stable logging format, use your own interceptor. |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public final class HttpLoggingInterceptor implements Interceptor { |
| | | private static final Charset UTF8 = StandardCharsets.UTF_8; |
| | | private final Logger logger; |
| | | private volatile BladeLogLevel level = BladeLogLevel.NONE; |
| | | |
| | | public interface Logger { |
| | | /** |
| | | * log |
| | | * @param message message |
| | | */ |
| | | void log(String message); |
| | | } |
| | | |
| | | public HttpLoggingInterceptor(Logger logger) { |
| | | this.logger = logger; |
| | | } |
| | | |
| | | /** |
| | | * Change the level at which this interceptor logs. |
| | | * @param level log Level |
| | | * @return HttpLoggingInterceptor |
| | | */ |
| | | public HttpLoggingInterceptor setLevel(BladeLogLevel level) { |
| | | this.level = Objects.requireNonNull(level, "level == null. Use Level.NONE instead."); |
| | | return this; |
| | | } |
| | | |
| | | public BladeLogLevel getLevel() { |
| | | return level; |
| | | } |
| | | |
| | | @Override |
| | | public Response intercept(Chain chain) throws IOException { |
| | | BladeLogLevel level = this.level; |
| | | |
| | | Request request = chain.request(); |
| | | if (level == BladeLogLevel.NONE) { |
| | | return chain.proceed(request); |
| | | } |
| | | |
| | | boolean logBody = level == BladeLogLevel.BODY; |
| | | boolean logHeaders = logBody || level == BladeLogLevel.HEADERS; |
| | | |
| | | RequestBody requestBody = request.body(); |
| | | boolean hasRequestBody = requestBody != null; |
| | | |
| | | Connection connection = chain.connection(); |
| | | String requestStartMessage = "--> " |
| | | + request.method() |
| | | + ' ' + request.url() |
| | | + (connection != null ? " " + connection.protocol() : ""); |
| | | if (!logHeaders && hasRequestBody) { |
| | | requestStartMessage += " (" + requestBody.contentLength() + "-byte body)"; |
| | | } |
| | | logger.log(requestStartMessage); |
| | | |
| | | if (logHeaders) { |
| | | if (hasRequestBody) { |
| | | // Request body headers are only present when installed as a network interceptor. Force |
| | | // them to be included (when available) so there values are known. |
| | | if (requestBody.contentType() != null) { |
| | | logger.log("Content-Type: " + requestBody.contentType()); |
| | | } |
| | | if (requestBody.contentLength() != -1) { |
| | | logger.log("Content-Length: " + requestBody.contentLength()); |
| | | } |
| | | } |
| | | |
| | | Headers headers = request.headers(); |
| | | for (int i = 0, count = headers.size(); i < count; i++) { |
| | | String name = headers.name(i); |
| | | // Skip headers from the request body as they are explicitly logged above. |
| | | if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) { |
| | | logger.log(name + ": " + headers.value(i)); |
| | | } |
| | | } |
| | | |
| | | if (!logBody || !hasRequestBody) { |
| | | logger.log("--> END " + request.method()); |
| | | } else if (bodyHasUnknownEncoding(request.headers())) { |
| | | logger.log("--> END " + request.method() + " (encoded body omitted)"); |
| | | } else { |
| | | Buffer buffer = new Buffer(); |
| | | requestBody.writeTo(buffer); |
| | | |
| | | Charset charset = UTF8; |
| | | MediaType contentType = requestBody.contentType(); |
| | | if (contentType != null) { |
| | | charset = contentType.charset(UTF8); |
| | | } |
| | | |
| | | logger.log(""); |
| | | if (isPlaintext(buffer)) { |
| | | logger.log(buffer.readString(charset)); |
| | | logger.log("--> END " + request.method() |
| | | + " (" + requestBody.contentLength() + "-byte body)"); |
| | | } else { |
| | | logger.log("--> END " + request.method() + " (binary " |
| | | + requestBody.contentLength() + "-byte body omitted)"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | long startNs = System.nanoTime(); |
| | | Response response; |
| | | try { |
| | | response = chain.proceed(request); |
| | | } catch (Exception e) { |
| | | logger.log("<-- HTTP FAILED: " + e); |
| | | throw e; |
| | | } |
| | | long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); |
| | | |
| | | ResponseBody responseBody = response.body(); |
| | | long contentLength = responseBody.contentLength(); |
| | | String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length"; |
| | | logger.log("<-- " |
| | | + response.code() |
| | | + (response.message().isEmpty() ? "" : ' ' + response.message()) |
| | | + ' ' + response.request().url() |
| | | + " (" + tookMs + "ms" + (!logHeaders ? ", " + bodySize + " body" : "") + ')'); |
| | | |
| | | if (logHeaders) { |
| | | Headers headers = response.headers(); |
| | | int count = headers.size(); |
| | | for (int i = 0; i < count; i++) { |
| | | logger.log(headers.name(i) + ": " + headers.value(i)); |
| | | } |
| | | |
| | | if (!logBody || !HttpHeaders.hasBody(response)) { |
| | | logger.log("<-- END HTTP"); |
| | | } else if (bodyHasUnknownEncoding(response.headers())) { |
| | | logger.log("<-- END HTTP (encoded body omitted)"); |
| | | } else { |
| | | BufferedSource source = responseBody.source(); |
| | | // Buffer the entire body. |
| | | source.request(Long.MAX_VALUE); |
| | | Buffer buffer = source.getBuffer(); |
| | | |
| | | Long gzippedLength = null; |
| | | if ("gzip".equalsIgnoreCase(headers.get("Content-Encoding"))) { |
| | | gzippedLength = buffer.size(); |
| | | GzipSource gzippedResponseBody = null; |
| | | try { |
| | | gzippedResponseBody = new GzipSource(buffer.clone()); |
| | | buffer = new Buffer(); |
| | | buffer.writeAll(gzippedResponseBody); |
| | | } finally { |
| | | if (gzippedResponseBody != null) { |
| | | gzippedResponseBody.close(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | Charset charset = UTF8; |
| | | MediaType contentType = responseBody.contentType(); |
| | | if (contentType != null) { |
| | | charset = contentType.charset(UTF8); |
| | | } |
| | | |
| | | if (!isPlaintext(buffer)) { |
| | | logger.log(""); |
| | | logger.log("<-- END HTTP (binary " + buffer.size() + "-byte body omitted)"); |
| | | return response; |
| | | } |
| | | |
| | | if (contentLength != 0) { |
| | | logger.log(""); |
| | | logger.log(buffer.clone().readString(charset)); |
| | | } |
| | | |
| | | if (gzippedLength != null) { |
| | | logger.log("<-- END HTTP (" + buffer.size() + "-byte, " |
| | | + gzippedLength + "-gzipped-byte body)"); |
| | | } else { |
| | | logger.log("<-- END HTTP (" + buffer.size() + "-byte body)"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return response; |
| | | } |
| | | |
| | | /** |
| | | * Returns true if the body in question probably contains human readable text. Uses a small sample |
| | | * of code points to detect unicode control characters commonly used in binary file signatures. |
| | | */ |
| | | private static boolean isPlaintext(Buffer buffer) { |
| | | try { |
| | | Buffer prefix = new Buffer(); |
| | | long byteCount = buffer.size() < 64 ? buffer.size() : 64; |
| | | buffer.copyTo(prefix, 0, byteCount); |
| | | for (int i = 0; i < 16; i++) { |
| | | if (prefix.exhausted()) { |
| | | break; |
| | | } |
| | | int codePoint = prefix.readUtf8CodePoint(); |
| | | if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } catch (EOFException e) { |
| | | // Truncated UTF-8 sequence. |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private boolean bodyHasUnknownEncoding(Headers headers) { |
| | | String contentEncoding = headers.get("Content-Encoding"); |
| | | return contentEncoding != null |
| | | && !"identity".equalsIgnoreCase(contentEncoding) |
| | | && !"gzip".equalsIgnoreCase(contentEncoding); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.cloud.http.logger; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | /** |
| | | * OkHttp Slf4j logger |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | public class OkHttpSlf4jLogger implements HttpLoggingInterceptor.Logger { |
| | | @Override |
| | | public void log(String message) { |
| | | log.info(message); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.cloud.sentinel; |
| | | |
| | | import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; |
| | | import com.alibaba.csp.sentinel.slots.block.BlockException; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.MediaType; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | /** |
| | | * Sentinelç»ä¸éæµçç¥ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class BladeBlockExceptionHandler implements BlockExceptionHandler { |
| | | @Override |
| | | public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception { |
| | | // Return 429 (Too Many Requests) by default. |
| | | response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); |
| | | response.setContentType(MediaType.APPLICATION_JSON_VALUE); |
| | | response.getWriter().print(JsonUtil.toJson(R.fail(e.getMessage()))); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright 2013-2018 the original author or authors. |
| | | * |
| | | * Licensed under the Apache License, Version 2.0 (the "License"); |
| | | * you may not use this file except in compliance with the License. |
| | | * You may obtain a copy of the License at |
| | | * |
| | | * https://www.apache.org/licenses/LICENSE-2.0 |
| | | * |
| | | * Unless required by applicable law or agreed to in writing, software |
| | | * distributed under the License is distributed on an "AS IS" BASIS, |
| | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| | | * See the License for the specific language governing permissions and |
| | | * limitations under the License. |
| | | */ |
| | | package org.springblade.core.cloud.sentinel; |
| | | |
| | | import com.alibaba.cloud.sentinel.feign.SentinelContractHolder; |
| | | import feign.Contract; |
| | | import feign.Feign; |
| | | import feign.InvocationHandlerFactory; |
| | | import feign.Target; |
| | | import org.springframework.cloud.openfeign.FallbackFactory; |
| | | import lombok.SneakyThrows; |
| | | import org.springblade.core.cloud.feign.BladeFallbackFactory; |
| | | import org.springframework.beans.BeansException; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.cloud.openfeign.FeignContext; |
| | | import org.springframework.context.ApplicationContext; |
| | | import org.springframework.context.ApplicationContextAware; |
| | | import org.springframework.core.annotation.AnnotationUtils; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.lang.reflect.InvocationHandler; |
| | | import java.lang.reflect.Method; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * feignéæsentinelèªå¨é
ç½® |
| | | * éå {@link com.alibaba.cloud.sentinel.feign.SentinelFeign} éé
ææ°API |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class BladeFeignSentinel { |
| | | |
| | | public static Builder builder() { |
| | | return new Builder(); |
| | | } |
| | | |
| | | public static final class Builder extends Feign.Builder implements ApplicationContextAware { |
| | | private Contract contract = new Contract.Default(); |
| | | private ApplicationContext applicationContext; |
| | | private FeignContext feignContext; |
| | | |
| | | @Override |
| | | public Feign.Builder invocationHandlerFactory( |
| | | InvocationHandlerFactory invocationHandlerFactory) { |
| | | throw new UnsupportedOperationException(); |
| | | } |
| | | |
| | | @Override |
| | | public Builder contract(Contract contract) { |
| | | this.contract = contract; |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public Feign build() { |
| | | super.invocationHandlerFactory(new InvocationHandlerFactory() { |
| | | @SneakyThrows |
| | | @Override |
| | | public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) { |
| | | // 注解åå¼ä»¥é¿å
循ç¯ä¾èµçé®é¢ |
| | | FeignClient feignClient = AnnotationUtils.findAnnotation(target.type(), FeignClient.class); |
| | | Class fallback = feignClient.fallback(); |
| | | Class fallbackFactory = feignClient.fallbackFactory(); |
| | | String contextId = feignClient.contextId(); |
| | | |
| | | if (!StringUtils.hasText(contextId)) { |
| | | contextId = feignClient.name(); |
| | | } |
| | | |
| | | Object fallbackInstance; |
| | | FallbackFactory fallbackFactoryInstance; |
| | | // 夿fallbackç±»å |
| | | if (void.class != fallback) { |
| | | fallbackInstance = getFromContext(contextId, "fallback", fallback, target.type()); |
| | | return new BladeSentinelInvocationHandler(target, dispatch, new FallbackFactory.Default(fallbackInstance)); |
| | | } |
| | | if (void.class != fallbackFactory) { |
| | | fallbackFactoryInstance = (FallbackFactory) getFromContext(contextId, "fallbackFactory", fallbackFactory, FallbackFactory.class); |
| | | return new BladeSentinelInvocationHandler(target, dispatch, fallbackFactoryInstance); |
| | | } |
| | | // é»è®¤fallbackFactory |
| | | BladeFallbackFactory bladeFallbackFactory = new BladeFallbackFactory(target); |
| | | return new BladeSentinelInvocationHandler(target, dispatch, bladeFallbackFactory); |
| | | } |
| | | |
| | | private Object getFromContext(String name, String type, Class fallbackType, Class targetType) { |
| | | Object fallbackInstance = feignContext.getInstance(name, fallbackType); |
| | | if (fallbackInstance == null) { |
| | | throw new IllegalStateException( |
| | | String.format("No %s instance of type %s found for feign client %s", |
| | | type, fallbackType, name) |
| | | ); |
| | | } |
| | | |
| | | if (!targetType.isAssignableFrom(fallbackType)) { |
| | | throw new IllegalStateException( |
| | | String.format("Incompatible %s instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s", |
| | | type, fallbackType, targetType, name) |
| | | ); |
| | | } |
| | | return fallbackInstance; |
| | | } |
| | | }); |
| | | super.contract(new SentinelContractHolder(contract)); |
| | | return super.build(); |
| | | } |
| | | |
| | | @Override |
| | | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { |
| | | this.applicationContext = applicationContext; |
| | | feignContext = this.applicationContext.getBean(FeignContext.class); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.cloud.sentinel; |
| | | |
| | | import com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration; |
| | | import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; |
| | | import feign.Feign; |
| | | import feign.RequestInterceptor; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springblade.core.cloud.feign.BladeFeignRequestInterceptor; |
| | | import org.springframework.beans.factory.config.ConfigurableBeanFactory; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Primary; |
| | | import org.springframework.context.annotation.Scope; |
| | | |
| | | /** |
| | | * Sentinelé
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AllArgsConstructor |
| | | @AutoConfiguration(before = SentinelFeignAutoConfiguration.class) |
| | | @ConditionalOnProperty(name = "feign.sentinel.enabled") |
| | | public class BladeSentinelAutoConfiguration { |
| | | |
| | | @Bean |
| | | @Primary |
| | | @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) |
| | | public Feign.Builder feignSentinelBuilder(RequestInterceptor requestInterceptor) { |
| | | return BladeFeignSentinel.builder().requestInterceptor(requestInterceptor); |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public RequestInterceptor requestInterceptor() { |
| | | return new BladeFeignRequestInterceptor(); |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public BlockExceptionHandler blockExceptionHandler() { |
| | | return new BladeBlockExceptionHandler(); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.cloud.sentinel; |
| | | |
| | | import com.alibaba.cloud.sentinel.SentinelProperties; |
| | | import com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor; |
| | | import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; |
| | | import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.DefaultBlockExceptionHandler; |
| | | import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser; |
| | | import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner; |
| | | import com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Import; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | | * å¤çsentinel2021å
¼å®¹é®é¢ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Import(BladeSentinelFilterConfiguration.class) |
| | | @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) |
| | | public class BladeSentinelFilterConfiguration { |
| | | |
| | | @Bean |
| | | public SentinelWebInterceptor sentinelWebInterceptor(SentinelWebMvcConfig sentinelWebMvcConfig) { |
| | | return new SentinelWebInterceptor(sentinelWebMvcConfig); |
| | | } |
| | | |
| | | @Bean |
| | | public SentinelWebMvcConfig sentinelWebMvcConfig(SentinelProperties properties, |
| | | Optional<UrlCleaner> urlCleanerOptional, Optional<BlockExceptionHandler> blockExceptionHandlerOptional, |
| | | Optional<RequestOriginParser> requestOriginParserOptional) { |
| | | SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig(); |
| | | sentinelWebMvcConfig.setHttpMethodSpecify(properties.getHttpMethodSpecify()); |
| | | sentinelWebMvcConfig.setWebContextUnify(properties.getWebContextUnify()); |
| | | |
| | | if (blockExceptionHandlerOptional.isPresent()) { |
| | | blockExceptionHandlerOptional.ifPresent(sentinelWebMvcConfig::setBlockExceptionHandler); |
| | | } else { |
| | | if (StringUtils.hasText(properties.getBlockPage())) { |
| | | sentinelWebMvcConfig.setBlockExceptionHandler( |
| | | ((request, response, e) -> response.sendRedirect(properties.getBlockPage()))); |
| | | } else { |
| | | sentinelWebMvcConfig.setBlockExceptionHandler(new DefaultBlockExceptionHandler()); |
| | | } |
| | | } |
| | | |
| | | urlCleanerOptional.ifPresent(sentinelWebMvcConfig::setUrlCleaner); |
| | | requestOriginParserOptional.ifPresent(sentinelWebMvcConfig::setOriginParser); |
| | | return sentinelWebMvcConfig; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.cloud.sentinel; |
| | | |
| | | import com.alibaba.cloud.sentinel.feign.SentinelContractHolder; |
| | | import com.alibaba.csp.sentinel.Entry; |
| | | import com.alibaba.csp.sentinel.EntryType; |
| | | import com.alibaba.csp.sentinel.SphU; |
| | | import com.alibaba.csp.sentinel.Tracer; |
| | | import com.alibaba.csp.sentinel.context.ContextUtil; |
| | | import com.alibaba.csp.sentinel.slots.block.BlockException; |
| | | import feign.Feign; |
| | | import feign.InvocationHandlerFactory; |
| | | import feign.MethodMetadata; |
| | | import feign.Target; |
| | | import org.springframework.cloud.openfeign.FallbackFactory; |
| | | |
| | | import java.lang.reflect.InvocationHandler; |
| | | import java.lang.reflect.InvocationTargetException; |
| | | import java.lang.reflect.Method; |
| | | import java.lang.reflect.Proxy; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.Map; |
| | | |
| | | import static feign.Util.checkNotNull; |
| | | |
| | | /** |
| | | * éå {@link com.alibaba.cloud.sentinel.feign.SentinelInvocationHandler} éé
ææ°API |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class BladeSentinelInvocationHandler implements InvocationHandler { |
| | | |
| | | private final Target<?> target; |
| | | |
| | | private final Map<Method, InvocationHandlerFactory.MethodHandler> dispatch; |
| | | |
| | | private FallbackFactory fallbackFactory; |
| | | |
| | | private Map<Method, Method> fallbackMethodMap; |
| | | |
| | | public BladeSentinelInvocationHandler(Target<?> target, Map<Method, InvocationHandlerFactory.MethodHandler> dispatch, |
| | | FallbackFactory fallbackFactory) { |
| | | this.target = checkNotNull(target, "target"); |
| | | this.dispatch = checkNotNull(dispatch, "dispatch"); |
| | | this.fallbackFactory = fallbackFactory; |
| | | this.fallbackMethodMap = toFallbackMethod(dispatch); |
| | | } |
| | | |
| | | public BladeSentinelInvocationHandler(Target<?> target, Map<Method, InvocationHandlerFactory.MethodHandler> dispatch) { |
| | | this.target = checkNotNull(target, "target"); |
| | | this.dispatch = checkNotNull(dispatch, "dispatch"); |
| | | } |
| | | |
| | | @Override |
| | | public Object invoke(final Object proxy, final Method method, final Object[] args) |
| | | throws Throwable { |
| | | if ("equals".equals(method.getName())) { |
| | | try { |
| | | Object otherHandler = args.length > 0 && args[0] != null |
| | | ? Proxy.getInvocationHandler(args[0]) : null; |
| | | return equals(otherHandler); |
| | | } catch (IllegalArgumentException e) { |
| | | return false; |
| | | } |
| | | } else if ("hashCode".equals(method.getName())) { |
| | | return hashCode(); |
| | | } else if ("toString".equals(method.getName())) { |
| | | return toString(); |
| | | } |
| | | |
| | | Object result; |
| | | InvocationHandlerFactory.MethodHandler methodHandler = this.dispatch.get(method); |
| | | // only handle by HardCodedTarget |
| | | if (target instanceof Target.HardCodedTarget) { |
| | | Target.HardCodedTarget hardCodedTarget = (Target.HardCodedTarget) target; |
| | | MethodMetadata methodMetadata = SentinelContractHolder.METADATA_MAP |
| | | .get(hardCodedTarget.type().getName() |
| | | + Feign.configKey(hardCodedTarget.type(), method)); |
| | | // resource default is HttpMethod:protocol://url |
| | | if (methodMetadata == null) { |
| | | result = methodHandler.invoke(args); |
| | | } else { |
| | | String resourceName = methodMetadata.template().method().toUpperCase() |
| | | + ":" + hardCodedTarget.url() + methodMetadata.template().path(); |
| | | Entry entry = null; |
| | | try { |
| | | ContextUtil.enter(resourceName); |
| | | entry = SphU.entry(resourceName, EntryType.OUT, 1, args); |
| | | result = methodHandler.invoke(args); |
| | | } catch (Throwable ex) { |
| | | // fallback handle |
| | | if (!BlockException.isBlockException(ex)) { |
| | | Tracer.trace(ex); |
| | | } |
| | | if (fallbackFactory != null) { |
| | | try { |
| | | Object fallbackResult = fallbackMethodMap.get(method) |
| | | .invoke(fallbackFactory.create(ex), args); |
| | | return fallbackResult; |
| | | } catch (IllegalAccessException e) { |
| | | // shouldn't happen as method is public due to being an |
| | | // interface |
| | | throw new AssertionError(e); |
| | | } catch (InvocationTargetException e) { |
| | | throw new AssertionError(e.getCause()); |
| | | } |
| | | } else { |
| | | // throw exception if fallbackFactory is null |
| | | throw ex; |
| | | } |
| | | } finally { |
| | | if (entry != null) { |
| | | entry.exit(1, args); |
| | | } |
| | | ContextUtil.exit(); |
| | | } |
| | | } |
| | | } else { |
| | | // other target type using default strategy |
| | | result = methodHandler.invoke(args); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(Object obj) { |
| | | if (obj instanceof BladeSentinelInvocationHandler) { |
| | | BladeSentinelInvocationHandler other = (BladeSentinelInvocationHandler) obj; |
| | | return target.equals(other.target); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return target.hashCode(); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return target.toString(); |
| | | } |
| | | |
| | | static Map<Method, Method> toFallbackMethod(Map<Method, InvocationHandlerFactory.MethodHandler> dispatch) { |
| | | Map<Method, Method> result = new LinkedHashMap<>(); |
| | | for (Method method : dispatch.keySet()) { |
| | | method.setAccessible(true); |
| | | result.put(method, method); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.server; |
| | | |
| | | import io.undertow.Undertow; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
| | | import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; |
| | | import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; |
| | | import org.springframework.boot.web.server.WebServerFactoryCustomizer; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | import static io.undertow.UndertowOptions.ENABLE_HTTP2; |
| | | |
| | | |
| | | /** |
| | | * Undertow http2 h2c é
ç½®ï¼å¯¹ servlet å¼å¯ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoConfiguration(before = ServletWebServerFactoryAutoConfiguration.class) |
| | | @ConditionalOnClass(Undertow.class) |
| | | public class UndertowHttp2Configuration { |
| | | |
| | | @Bean |
| | | public WebServerFactoryCustomizer<UndertowServletWebServerFactory> undertowHttp2WebServerFactoryCustomizer() { |
| | | return factory -> factory.addBuilderCustomizers(builder -> builder.setServerOption(ENABLE_HTTP2, true)); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.cloud.version; |
| | | |
| | | import lombok.Getter; |
| | | import org.springframework.http.MediaType; |
| | | |
| | | /** |
| | | * blade Media Typesï¼application/vnd.github.VERSION+json |
| | | * |
| | | * <p> |
| | | * https://developer.github.com/v3/media/ |
| | | * </p> |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | public class BladeMediaType { |
| | | private static final String MEDIA_TYPE_TEMP = "application/vnd.%s.%s+json"; |
| | | |
| | | private final String appName = "blade"; |
| | | private final String version; |
| | | private final MediaType mediaType; |
| | | |
| | | public BladeMediaType(String version) { |
| | | this.version = version; |
| | | this.mediaType = MediaType.valueOf(String.format(MEDIA_TYPE_TEMP, appName, version)); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return mediaType.toString(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.version; |
| | | |
| | | import org.springblade.core.cloud.annotation.ApiVersion; |
| | | import org.springblade.core.cloud.annotation.UrlVersion; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springframework.core.annotation.AnnotatedElementUtils; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.web.method.HandlerMethod; |
| | | import org.springframework.web.servlet.mvc.method.RequestMappingInfo; |
| | | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * urlçæ¬å·å¤ç å header çæ¬å¤ç |
| | | * |
| | | * <p> |
| | | * url: /v1/user/{id} |
| | | * header: Accept application/vnd.blade.VERSION+json |
| | | * </p> |
| | | * |
| | | * 注æï¼c 代表客æ·ç«¯çæ¬ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeRequestMappingHandlerMapping extends RequestMappingHandlerMapping { |
| | | |
| | | @Nullable |
| | | @Override |
| | | protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { |
| | | RequestMappingInfo mappinginfo = super.getMappingForMethod(method, handlerType); |
| | | if (mappinginfo != null) { |
| | | RequestMappingInfo apiVersionMappingInfo = getApiVersionMappingInfo(method, handlerType); |
| | | return apiVersionMappingInfo == null ? mappinginfo : apiVersionMappingInfo.combine(mappinginfo); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Nullable |
| | | private RequestMappingInfo getApiVersionMappingInfo(Method method, Class<?> handlerType) { |
| | | // url ä¸ççæ¬ï¼ä¼å
è·åæ¹æ³ä¸ççæ¬ |
| | | UrlVersion urlVersion = AnnotatedElementUtils.findMergedAnnotation(method, UrlVersion.class); |
| | | // 忬¡å°è¯ç±»ä¸ççæ¬ |
| | | if (urlVersion == null || StringUtil.isBlank(urlVersion.value())) { |
| | | urlVersion = AnnotatedElementUtils.findMergedAnnotation(handlerType, UrlVersion.class); |
| | | } |
| | | // Media Types çæ¬ä¿¡æ¯ |
| | | ApiVersion apiVersion = AnnotatedElementUtils.findMergedAnnotation(method, ApiVersion.class); |
| | | // 忬¡å°è¯ç±»ä¸ççæ¬ |
| | | if (apiVersion == null || StringUtil.isBlank(apiVersion.value())) { |
| | | apiVersion = AnnotatedElementUtils.findMergedAnnotation(handlerType, ApiVersion.class); |
| | | } |
| | | boolean nonUrlVersion = urlVersion == null || StringUtil.isBlank(urlVersion.value()); |
| | | boolean nonApiVersion = apiVersion == null || StringUtil.isBlank(apiVersion.value()); |
| | | // å
夿忶ä¸çº¯å¨ |
| | | if (nonUrlVersion && nonApiVersion) { |
| | | return null; |
| | | } |
| | | // 妿 header çæ¬ä¸åå¨ |
| | | RequestMappingInfo.Builder mappingInfoBuilder = null; |
| | | if (nonApiVersion) { |
| | | mappingInfoBuilder = RequestMappingInfo.paths(urlVersion.value()); |
| | | } else { |
| | | mappingInfoBuilder = RequestMappingInfo.paths(StringPool.EMPTY); |
| | | } |
| | | // 妿urlçæ¬ä¸åå¨ |
| | | if (nonUrlVersion) { |
| | | String vsersionMediaTypes = new BladeMediaType(apiVersion.value()).toString(); |
| | | mappingInfoBuilder.produces(vsersionMediaTypes); |
| | | } |
| | | return mappingInfoBuilder.build(); |
| | | } |
| | | |
| | | @Override |
| | | protected void handlerMethodsInitialized(Map<RequestMappingInfo, HandlerMethod> handlerMethods) { |
| | | // æå°è·¯ç±ä¿¡æ¯ spring boot 2.1 廿äºè¿ä¸ª æ¥å¿çæå° |
| | | if (logger.isInfoEnabled()) { |
| | | for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) { |
| | | RequestMappingInfo mapping = entry.getKey(); |
| | | HandlerMethod handlerMethod = entry.getValue(); |
| | | logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod); |
| | | } |
| | | } |
| | | super.handlerMethodsInitialized(handlerMethods); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.version; |
| | | |
| | | import feign.MethodMetadata; |
| | | import org.springblade.core.cloud.annotation.ApiVersion; |
| | | import org.springblade.core.cloud.annotation.UrlVersion; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springframework.cloud.openfeign.AnnotatedParameterProcessor; |
| | | import org.springframework.cloud.openfeign.support.SpringMvcContract; |
| | | import org.springframework.core.annotation.AnnotatedElementUtils; |
| | | import org.springframework.core.convert.ConversionService; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | |
| | | import java.lang.annotation.Annotation; |
| | | import java.lang.reflect.Method; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æ¯æ blade-boot ç çæ¬ å¤ç |
| | | * |
| | | * @see org.springblade.core.cloud.annotation.UrlVersion |
| | | * @see org.springblade.core.cloud.annotation.ApiVersion |
| | | * @author L.cm |
| | | */ |
| | | public class BladeSpringMvcContract extends SpringMvcContract { |
| | | |
| | | public BladeSpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors, ConversionService conversionService) { |
| | | super(annotatedParameterProcessors, conversionService); |
| | | } |
| | | |
| | | @Override |
| | | protected void processAnnotationOnMethod(MethodMetadata data, Annotation methodAnnotation, Method method) { |
| | | if (RequestMapping.class.isInstance(methodAnnotation) || methodAnnotation.annotationType().isAnnotationPresent(RequestMapping.class)) { |
| | | Class<?> targetType = method.getDeclaringClass(); |
| | | // url ä¸ççæ¬ï¼ä¼å
è·åæ¹æ³ä¸ççæ¬ |
| | | UrlVersion urlVersion = AnnotatedElementUtils.findMergedAnnotation(method, UrlVersion.class); |
| | | // 忬¡å°è¯ç±»ä¸ççæ¬ |
| | | if (urlVersion == null || StringUtil.isBlank(urlVersion.value())) { |
| | | urlVersion = AnnotatedElementUtils.findMergedAnnotation(targetType, UrlVersion.class); |
| | | } |
| | | if (urlVersion != null && StringUtil.isNotBlank(urlVersion.value())) { |
| | | String versionUrl = "/" + urlVersion.value(); |
| | | data.template().uri(versionUrl); |
| | | } |
| | | |
| | | // 注æï¼å¨ç¶ç±»ä¹å æ·»å urlçæ¬ï¼å¨ç¶ç±»ä¹åï¼å¤ç Media Types çæ¬ |
| | | super.processAnnotationOnMethod(data, methodAnnotation, method); |
| | | |
| | | // å¤ç Media Types çæ¬ä¿¡æ¯ |
| | | ApiVersion apiVersion = AnnotatedElementUtils.findMergedAnnotation(method, ApiVersion.class); |
| | | // 忬¡å°è¯ç±»ä¸ççæ¬ |
| | | if (apiVersion == null || StringUtil.isBlank(apiVersion.value())) { |
| | | apiVersion = AnnotatedElementUtils.findMergedAnnotation(targetType, ApiVersion.class); |
| | | } |
| | | if (apiVersion != null && StringUtil.isNotBlank(apiVersion.value())) { |
| | | BladeMediaType bladeMediaType = new BladeMediaType(apiVersion.value()); |
| | | data.template().header(HttpHeaders.ACCEPT, bladeMediaType.toString()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åèï¼https://gist.github.com/rmfish/0ed59a9af6c05157be2a60c9acea2a10 |
| | | * @param annotations 注解 |
| | | * @param paramIndex åæ°ç´¢å¼ |
| | | * @return æ¯å¦ http 注解 |
| | | */ |
| | | @Override |
| | | protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) { |
| | | boolean httpAnnotation = super.processAnnotationsOnParameter(data, annotations, paramIndex); |
| | | // å¨ springMvc ä¸å¦ææ¯ Get 请æ±ä¸åæ°ä¸æ¯å¯¹è±¡ 没æå£°æä¸º@RequestBody åé»è®¤ä¸º Param |
| | | if (!httpAnnotation && StringPool.GET.equals(data.template().method().toUpperCase())) { |
| | | for (Annotation parameterAnnotation : annotations) { |
| | | if (!(parameterAnnotation instanceof RequestBody)) { |
| | | return false; |
| | | } |
| | | } |
| | | data.queryMapIndex(paramIndex); |
| | | return true; |
| | | } |
| | | return httpAnnotation; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.version; |
| | | |
| | | import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations; |
| | | import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; |
| | | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; |
| | | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; |
| | | |
| | | /** |
| | | * urlçæ¬å·å¤ç |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeWebMvcRegistrations implements WebMvcRegistrations { |
| | | @Override |
| | | public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { |
| | | return new BladeRequestMappingHandlerMapping(); |
| | | } |
| | | |
| | | @Override |
| | | public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public ExceptionHandlerExceptionResolver getExceptionHandlerExceptionResolver() { |
| | | return null; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.version; |
| | | |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; |
| | | import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | /** |
| | | * urlçæ¬å·å¤ç |
| | | * |
| | | * åèï¼https://gitee.com/lianqu1990/spring-boot-starter-version-mapping |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoConfiguration |
| | | @ConditionalOnWebApplication |
| | | public class VersionMappingAutoConfiguration { |
| | | @Bean |
| | | public WebMvcRegistrations bladeWebMvcRegistrations() { |
| | | return new BladeWebMvcRegistrations(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <groupId>org.springblade</groupId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-context</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-tool</artifactId> |
| | | </dependency> |
| | | <!-- Auto --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context; |
| | | |
| | | import org.slf4j.MDC; |
| | | import org.springblade.core.tool.utils.ThreadLocalUtil; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.util.Map; |
| | | import java.util.concurrent.Callable; |
| | | |
| | | /** |
| | | * å¤çº¿ç¨ä¸ä¼ é context å mdc |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeCallableWrapper<V> implements Callable<V> { |
| | | private final Callable<V> delegate; |
| | | private final Map<String, Object> tlMap; |
| | | /** |
| | | * logback 䏿å¯è½ä¸º null |
| | | */ |
| | | @Nullable |
| | | private final Map<String, String> mdcMap; |
| | | |
| | | public BladeCallableWrapper(Callable<V> callable) { |
| | | this.delegate = callable; |
| | | this.tlMap = ThreadLocalUtil.getAll(); |
| | | this.mdcMap = MDC.getCopyOfContextMap(); |
| | | } |
| | | |
| | | @Override |
| | | public V call() throws Exception { |
| | | if (!tlMap.isEmpty()) { |
| | | ThreadLocalUtil.put(tlMap); |
| | | } |
| | | if (mdcMap != null && !mdcMap.isEmpty()) { |
| | | MDC.setContextMap(mdcMap); |
| | | } |
| | | try { |
| | | return delegate.call(); |
| | | } finally { |
| | | tlMap.clear(); |
| | | if (mdcMap != null) { |
| | | mdcMap.clear(); |
| | | } |
| | | ThreadLocalUtil.clear(); |
| | | MDC.clear(); |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context; |
| | | |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.util.function.Function; |
| | | |
| | | /** |
| | | * Bladeå¾®æå¡ä¸ä¸æ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public interface BladeContext { |
| | | |
| | | /** |
| | | * è·å è¯·æ± id |
| | | * |
| | | * @return 请æ±id |
| | | */ |
| | | @Nullable |
| | | String getRequestId(); |
| | | |
| | | /** |
| | | * è´¦å·id |
| | | * |
| | | * @return è´¦å·id |
| | | */ |
| | | @Nullable |
| | | String getAccountId(); |
| | | |
| | | /** |
| | | * è·åç§æ·id |
| | | * |
| | | * @return ç§æ·id |
| | | */ |
| | | @Nullable |
| | | String getTenantId(); |
| | | |
| | | /** |
| | | * è·åä¸ä¸æä¸çæ°æ® |
| | | * |
| | | * @param ctxKey ä¸ä¸æä¸çkey |
| | | * @return è¿å对象 |
| | | */ |
| | | @Nullable |
| | | String get(String ctxKey); |
| | | |
| | | /** |
| | | * è·åä¸ä¸æä¸çæ°æ® |
| | | * |
| | | * @param ctxKey ä¸ä¸æä¸çkey |
| | | * @param function 彿°å¼ |
| | | * @param <T> æ³å对象 |
| | | * @return è¿å对象 |
| | | */ |
| | | @Nullable |
| | | <T> T get(String ctxKey, Function<String, T> function); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context; |
| | | |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | |
| | | /** |
| | | * HttpHeaders è·åå¨ï¼ç¨äºè·¨æå¡å线ç¨çä¼ éï¼ |
| | | * <p> |
| | | * ææ¶ä¸æ¯æ webfluxã |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public interface BladeHttpHeadersGetter { |
| | | |
| | | /** |
| | | * è·å HttpHeaders |
| | | * |
| | | * @return HttpHeaders |
| | | */ |
| | | @Nullable |
| | | HttpHeaders get(); |
| | | |
| | | /** |
| | | * è·å HttpHeaders |
| | | * |
| | | * @param request è¯·æ± |
| | | * @return HttpHeaders |
| | | */ |
| | | @Nullable |
| | | HttpHeaders get(HttpServletRequest request); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context; |
| | | |
| | | import org.slf4j.MDC; |
| | | import org.springblade.core.tool.utils.ThreadLocalUtil; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * å¤çº¿ç¨ä¸ä¼ é context å mdc |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeRunnableWrapper implements Runnable { |
| | | private final Runnable delegate; |
| | | private final Map<String, Object> tlMap; |
| | | /** |
| | | * logback 䏿å¯è½ä¸º null |
| | | */ |
| | | @Nullable |
| | | private final Map<String, String> mdcMap; |
| | | |
| | | public BladeRunnableWrapper(Runnable runnable) { |
| | | this.delegate = runnable; |
| | | this.tlMap = ThreadLocalUtil.getAll(); |
| | | this.mdcMap = MDC.getCopyOfContextMap(); |
| | | } |
| | | |
| | | @Override |
| | | public void run() { |
| | | if (!tlMap.isEmpty()) { |
| | | ThreadLocalUtil.put(tlMap); |
| | | } |
| | | if (mdcMap != null && !mdcMap.isEmpty()) { |
| | | MDC.setContextMap(mdcMap); |
| | | } |
| | | try { |
| | | delegate.run(); |
| | | } finally { |
| | | tlMap.clear(); |
| | | if (mdcMap != null) { |
| | | mdcMap.clear(); |
| | | } |
| | | ThreadLocalUtil.clear(); |
| | | MDC.clear(); |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context; |
| | | |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springblade.core.context.props.BladeContextProperties; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springblade.core.tool.utils.ThreadLocalUtil; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.util.function.Function; |
| | | |
| | | import static org.springblade.core.tool.constant.BladeConstant.CONTEXT_KEY; |
| | | |
| | | /** |
| | | * blade servlet ä¸ä¸æï¼è·¨çº¿ç¨å¤±æ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) |
| | | public class BladeServletContext implements BladeContext { |
| | | private final BladeContextProperties contextProperties; |
| | | private final BladeHttpHeadersGetter httpHeadersGetter; |
| | | |
| | | @Nullable |
| | | @Override |
| | | public String getRequestId() { |
| | | return get(contextProperties.getHeaders().getRequestId()); |
| | | } |
| | | |
| | | @Nullable |
| | | @Override |
| | | public String getAccountId() { |
| | | return get(contextProperties.getHeaders().getAccountId()); |
| | | } |
| | | |
| | | @Nullable |
| | | @Override |
| | | public String getTenantId() { |
| | | return get(contextProperties.getHeaders().getTenantId()); |
| | | } |
| | | |
| | | @Nullable |
| | | @Override |
| | | public String get(String ctxKey) { |
| | | HttpHeaders headers = ThreadLocalUtil.getIfAbsent(CONTEXT_KEY, httpHeadersGetter::get); |
| | | if (headers == null || headers.isEmpty()) { |
| | | return null; |
| | | } |
| | | return headers.getFirst(ctxKey); |
| | | } |
| | | |
| | | @Nullable |
| | | @Override |
| | | public <T> T get(String ctxKey, Function<String, T> function) { |
| | | String ctxValue = get(ctxKey); |
| | | if (StringUtil.isBlank(ctxValue)) { |
| | | return null; |
| | | } |
| | | return function.apply(ctxKey); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context; |
| | | |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springblade.core.context.props.BladeContextProperties; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.util.Enumeration; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * HttpHeaders è·åå¨ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) |
| | | public class ServletHttpHeadersGetter implements BladeHttpHeadersGetter { |
| | | private final BladeContextProperties properties; |
| | | |
| | | @Nullable |
| | | @Override |
| | | public HttpHeaders get() { |
| | | HttpServletRequest request = WebUtil.getRequest(); |
| | | if (request == null) { |
| | | return null; |
| | | } |
| | | return get(request); |
| | | } |
| | | |
| | | @Nullable |
| | | @Override |
| | | public HttpHeaders get(HttpServletRequest request) { |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | List<String> crossHeaders = properties.getCrossHeaders(); |
| | | // ä¼ é请æ±å¤´ |
| | | Enumeration<String> headerNames = request.getHeaderNames(); |
| | | if (headerNames != null) { |
| | | List<String> allowed = properties.getHeaders().getAllowed(); |
| | | while (headerNames.hasMoreElements()) { |
| | | String key = headerNames.nextElement(); |
| | | // åªæ¯æé
ç½®ç header |
| | | if (crossHeaders.contains(key) || allowed.contains(key)) { |
| | | String values = request.getHeader(key); |
| | | // header value ä¸ä¸ºç©ºç ä¼ é |
| | | if (StringUtil.isNotBlank(values)) { |
| | | headers.add(key, values); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return headers; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context.config; |
| | | |
| | | import org.springblade.core.context.BladeContext; |
| | | import org.springblade.core.context.BladeHttpHeadersGetter; |
| | | import org.springblade.core.context.BladeServletContext; |
| | | import org.springblade.core.context.ServletHttpHeadersGetter; |
| | | import org.springblade.core.context.props.BladeContextProperties; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.core.Ordered; |
| | | import org.springframework.core.annotation.Order; |
| | | |
| | | /** |
| | | * blade æå¡ä¸ä¸æé
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoConfiguration |
| | | @Order(Ordered.HIGHEST_PRECEDENCE) |
| | | @EnableConfigurationProperties(BladeContextProperties.class) |
| | | public class BladeContextAutoConfiguration { |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public BladeHttpHeadersGetter bladeHttpHeadersGetter(BladeContextProperties contextProperties) { |
| | | return new ServletHttpHeadersGetter(contextProperties); |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public BladeContext bladeContext(BladeContextProperties contextProperties, BladeHttpHeadersGetter httpHeadersGetter) { |
| | | return new BladeServletContext(contextProperties, httpHeadersGetter); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context.config; |
| | | |
| | | import org.springblade.core.context.BladeHttpHeadersGetter; |
| | | import org.springblade.core.context.listener.BladeServletRequestListener; |
| | | import org.springblade.core.context.props.BladeContextProperties; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; |
| | | import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | /** |
| | | * Servlet çå¬å¨èªå¨é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoConfiguration |
| | | @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) |
| | | public class BladeServletListenerConfiguration { |
| | | |
| | | @Bean |
| | | public ServletListenerRegistrationBean<?> registerCustomListener(BladeContextProperties properties, |
| | | BladeHttpHeadersGetter httpHeadersGetter) { |
| | | return new ServletListenerRegistrationBean<>(new BladeServletRequestListener(properties, httpHeadersGetter)); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context.listener; |
| | | |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.slf4j.MDC; |
| | | import org.springblade.core.context.BladeHttpHeadersGetter; |
| | | import org.springblade.core.context.props.BladeContextProperties; |
| | | import org.springblade.core.tool.constant.BladeConstant; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springblade.core.tool.utils.ThreadLocalUtil; |
| | | import org.springframework.http.HttpHeaders; |
| | | |
| | | import javax.servlet.ServletRequestEvent; |
| | | import javax.servlet.ServletRequestListener; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | |
| | | /** |
| | | * Servlet 请æ±çå¬å¨ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @RequiredArgsConstructor |
| | | public class BladeServletRequestListener implements ServletRequestListener { |
| | | private final BladeContextProperties contextProperties; |
| | | private final BladeHttpHeadersGetter httpHeadersGetter; |
| | | |
| | | @Override |
| | | public void requestInitialized(ServletRequestEvent event) { |
| | | HttpServletRequest request = (HttpServletRequest) event.getServletRequest(); |
| | | // MDC è·åéä¼ ç åé |
| | | BladeContextProperties.Headers headers = contextProperties.getHeaders(); |
| | | String requestId = request.getHeader(headers.getRequestId()); |
| | | if (StringUtil.isNotBlank(requestId)) { |
| | | MDC.put(BladeConstant.MDC_REQUEST_ID_KEY, requestId); |
| | | } |
| | | String accountId = request.getHeader(headers.getAccountId()); |
| | | if (StringUtil.isNotBlank(accountId)) { |
| | | MDC.put(BladeConstant.MDC_ACCOUNT_ID_KEY, accountId); |
| | | } |
| | | String tenantId = request.getHeader(headers.getTenantId()); |
| | | if (StringUtil.isNotBlank(tenantId)) { |
| | | MDC.put(BladeConstant.MDC_TENANT_ID_KEY, tenantId); |
| | | } |
| | | // å¤ç contextï¼ç´æ¥ä¼ é requestï¼å 为 spring ä¸çå°æªåå§å宿 |
| | | HttpHeaders httpHeaders = httpHeadersGetter.get(request); |
| | | ThreadLocalUtil.put(BladeConstant.CONTEXT_KEY, httpHeaders); |
| | | } |
| | | |
| | | @Override |
| | | public void requestDestroyed(ServletRequestEvent event) { |
| | | // ä¼è¯éæ¯æ¶ï¼æ¸
é¤ä¸ä¸æ |
| | | ThreadLocalUtil.clear(); |
| | | // ä¼è¯éæ¯æ¶ï¼æ¸
é¤ mdc |
| | | MDC.remove(BladeConstant.MDC_REQUEST_ID_KEY); |
| | | MDC.remove(BladeConstant.MDC_ACCOUNT_ID_KEY); |
| | | MDC.remove(BladeConstant.MDC_TENANT_ID_KEY); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.context.props; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import org.springblade.core.launch.constant.TokenConstant; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Headers é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @ConfigurationProperties(BladeContextProperties.PREFIX) |
| | | public class BladeContextProperties { |
| | | /** |
| | | * é
ç½®åç¼ |
| | | */ |
| | | public static final String PREFIX = "blade.context"; |
| | | /** |
| | | * ä¸ä¸æä¼ éç headers ä¿¡æ¯ |
| | | */ |
| | | private Headers headers = new Headers(); |
| | | |
| | | @Getter |
| | | @Setter |
| | | public static class Headers { |
| | | /** |
| | | * 请æ±idï¼é»è®¤ï¼Blade-RequestId |
| | | */ |
| | | private String requestId = "Blade-RequestId"; |
| | | /** |
| | | * ç¨äº èåå± åè°ç¨å±ä¼ éç¨æ·ä¿¡æ¯ ç请æ±å¤´ï¼é»è®¤ï¼Blade-AccountId |
| | | */ |
| | | private String accountId = "Blade-AccountId"; |
| | | /** |
| | | * ç¨äº èåå± åè°ç¨å±ä¼ éç§æ·id ç请æ±å¤´ï¼é»è®¤ï¼Blade-TenantId |
| | | */ |
| | | private String tenantId = "Blade-TenantId"; |
| | | /** |
| | | * èªå®ä¹ RestTemplate å Feign éä¼ å°ä¸å±ç Headers åç§°å表 |
| | | */ |
| | | private List<String> allowed = Arrays.asList("X-Real-IP", "x-forwarded-for", "version", "VERSION", "authorization", "Authorization", TokenConstant.HEADER.toLowerCase(), TokenConstant.HEADER); |
| | | } |
| | | |
| | | /** |
| | | * è·åè·¨æå¡ç请æ±å¤´ |
| | | * |
| | | * @return 请æ±å¤´å表 |
| | | */ |
| | | public List<String> getCrossHeaders() { |
| | | List<String> headerList = new ArrayList<>(); |
| | | headerList.add(headers.getRequestId()); |
| | | headerList.add(headers.getAccountId()); |
| | | headerList.add(headers.getTenantId()); |
| | | headerList.addAll(headers.getAllowed()); |
| | | return headerList; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <groupId>org.springblade</groupId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-db</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <dependencies> |
| | | <!--Blade--> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-tool</artifactId> |
| | | </dependency> |
| | | <!--Spring--> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-jdbc</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>tomcat-jdbc</artifactId> |
| | | <groupId>org.apache.tomcat</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <!--Mybatis--> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-boot-starter</artifactId> |
| | | </dependency> |
| | | <!-- Druid --> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>druid-spring-boot-starter</artifactId> |
| | | </dependency> |
| | | <!-- MySql --> |
| | | <dependency> |
| | | <groupId>mysql</groupId> |
| | | <artifactId>mysql-connector-java</artifactId> |
| | | </dependency> |
| | | <!-- Oracle --> |
| | | <dependency> |
| | | <groupId>com.oracle</groupId> |
| | | <artifactId>ojdbc7</artifactId> |
| | | <optional>true</optional> |
| | | </dependency> |
| | | <!-- PostgreSql --> |
| | | <dependency> |
| | | <groupId>org.postgresql</groupId> |
| | | <artifactId>postgresql</artifactId> |
| | | <optional>true</optional> |
| | | </dependency> |
| | | <!-- SqlServer --> |
| | | <dependency> |
| | | <groupId>com.microsoft.sqlserver</groupId> |
| | | <artifactId>mssql-jdbc</artifactId> |
| | | <optional>true</optional> |
| | | </dependency> |
| | | <!-- DaMeng --> |
| | | <dependency> |
| | | <groupId>com.dameng</groupId> |
| | | <artifactId>DmJdbcDriver18</artifactId> |
| | | <optional>true</optional> |
| | | </dependency> |
| | | <!-- Auto --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.db.config; |
| | | |
| | | import org.springblade.core.launch.props.BladePropertySource; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | |
| | | /** |
| | | * æ°æ®æºé
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AutoConfiguration |
| | | @BladePropertySource(value = "classpath:/blade-db.yml") |
| | | public class DbConfiguration { |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * Created by Blade. |
| | | * |
| | | * @author zhuangqian |
| | | */ |
| | | package org.springblade.core.db; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | #spring-datasourceé
ç½® |
| | | spring: |
| | | datasource: |
| | | driver-class-name: com.mysql.cj.jdbc.Driver |
| | | druid: |
| | | initial-size: 5 |
| | | max-active: 20 |
| | | min-idle: 5 |
| | | max-wait: 60000 |
| | | # MySqlãPostgreSQLæ ¡éª |
| | | validation-query: select 1 |
| | | # Oracleæ ¡éª |
| | | #validation-query: select 1 from dual |
| | | validation-query-timeout: 2000 |
| | | test-on-borrow: false |
| | | test-on-return: false |
| | | test-while-idle: true |
| | | time-between-eviction-runs-millis: 60000 |
| | | min-evictable-idle-time-millis: 300000 |
| | | stat-view-servlet: |
| | | enabled: true |
| | | login-username: blade |
| | | login-password: 1qaz@WSX |
| | | web-stat-filter: |
| | | enabled: true |
| | | url-pattern: /* |
| | | exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*' |
| | | session-stat-enable: true |
| | | session-stat-max-count: 10 |
| | | #hikari: |
| | | #connection-test-query: SELECT 1 FROM DUAL |
| | | #connection-timeout: 30000 |
| | | #maximum-pool-size: 5 |
| | | #max-lifetime: 1800000 |
| | | #minimum-idle: 1 |
| | | |
| | | |
| | | |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <groupId>org.springblade</groupId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-launch</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <dependencies> |
| | | <!--Spring--> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-web</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-tomcat</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-undertow</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.cloud</groupId> |
| | | <artifactId>spring-cloud-starter-bootstrap</artifactId> |
| | | </dependency> |
| | | <!-- Auto --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch; |
| | | |
| | | import org.springblade.core.launch.constant.AppConstant; |
| | | import org.springblade.core.launch.constant.NacosConstant; |
| | | import org.springblade.core.launch.service.LauncherService; |
| | | import org.springframework.boot.builder.SpringApplicationBuilder; |
| | | import org.springframework.context.ConfigurableApplicationContext; |
| | | import org.springframework.core.env.*; |
| | | import org.springframework.util.Assert; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.*; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 项ç®å¯å¨å¨ï¼æå®ç¯å¢åéé®é¢ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class BladeApplication { |
| | | |
| | | /** |
| | | * Create an application context |
| | | * java -jar app.jar --spring.profiles.active=prod --server.port=2333 |
| | | * |
| | | * @param appName application name |
| | | * @param source The sources |
| | | * @return an application context created from the current state |
| | | */ |
| | | public static ConfigurableApplicationContext run(String appName, Class source, String... args) { |
| | | SpringApplicationBuilder builder = createSpringApplicationBuilder(appName, source, args); |
| | | return builder.run(args); |
| | | } |
| | | |
| | | public static SpringApplicationBuilder createSpringApplicationBuilder(String appName, Class source, String... args) { |
| | | Assert.hasText(appName, "[appName]æå¡åä¸è½ä¸ºç©º"); |
| | | // 读åç¯å¢åéï¼ä½¿ç¨spring bootçè§å |
| | | ConfigurableEnvironment environment = new StandardEnvironment(); |
| | | MutablePropertySources propertySources = environment.getPropertySources(); |
| | | propertySources.addFirst(new SimpleCommandLinePropertySource(args)); |
| | | propertySources.addLast(new MapPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, environment.getSystemProperties())); |
| | | propertySources.addLast(new SystemEnvironmentPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, environment.getSystemEnvironment())); |
| | | // è·åé
ç½®çç¯å¢åé |
| | | String[] activeProfiles = environment.getActiveProfiles(); |
| | | // 夿ç¯å¢:devãtestãprod |
| | | List<String> profiles = Arrays.asList(activeProfiles); |
| | | // é¢è®¾çç¯å¢ |
| | | List<String> presetProfiles = new ArrayList<>(Arrays.asList(AppConstant.DEV_CODE, AppConstant.TEST_CODE, AppConstant.PROD_CODE)); |
| | | // 交é |
| | | presetProfiles.retainAll(profiles); |
| | | // å½åä½¿ç¨ |
| | | List<String> activeProfileList = new ArrayList<>(profiles); |
| | | Function<Object[], String> joinFun = StringUtils::arrayToCommaDelimitedString; |
| | | SpringApplicationBuilder builder = new SpringApplicationBuilder(source); |
| | | String profile; |
| | | if (activeProfileList.isEmpty()) { |
| | | // é»è®¤devå¼å |
| | | profile = AppConstant.DEV_CODE; |
| | | activeProfileList.add(profile); |
| | | builder.profiles(profile); |
| | | } else if (activeProfileList.size() == 1) { |
| | | profile = activeProfileList.get(0); |
| | | } else { |
| | | // åæ¶åå¨devãtestãprodç¯å¢æ¶ |
| | | throw new RuntimeException("åæ¶åå¨ç¯å¢åé:[" + StringUtils.arrayToCommaDelimitedString(activeProfiles) + "]"); |
| | | } |
| | | String startJarPath = BladeApplication.class.getResource("/").getPath().split("!")[0]; |
| | | String activePros = joinFun.apply(activeProfileList.toArray()); |
| | | System.out.printf("----å¯å¨ä¸ï¼è¯»åå°çç¯å¢åé:[%s]ï¼jarå°å:[%s]----%n", activePros, startJarPath); |
| | | Properties props = System.getProperties(); |
| | | props.setProperty("spring.application.name", appName); |
| | | props.setProperty("spring.profiles.active", profile); |
| | | props.setProperty("info.version", AppConstant.APPLICATION_VERSION); |
| | | props.setProperty("info.desc", appName); |
| | | props.setProperty("file.encoding", StandardCharsets.UTF_8.name()); |
| | | props.setProperty("blade.env", profile); |
| | | props.setProperty("blade.name", appName); |
| | | props.setProperty("blade.is-local", String.valueOf(isLocalDev())); |
| | | props.setProperty("blade.dev-mode", profile.equals(AppConstant.PROD_CODE) ? "false" : "true"); |
| | | props.setProperty("blade.service.version", AppConstant.APPLICATION_VERSION); |
| | | props.setProperty("loadbalancer.client.name", appName); |
| | | Properties defaultProperties = new Properties(); |
| | | defaultProperties.setProperty("spring.main.allow-bean-definition-overriding", "true"); |
| | | defaultProperties.setProperty("spring.sleuth.sampler.percentage", "1.0"); |
| | | defaultProperties.setProperty("spring.cloud.alibaba.seata.tx-service-group", appName.concat(NacosConstant.NACOS_GROUP_SUFFIX)); |
| | | defaultProperties.setProperty("spring.cloud.nacos.config.file-extension", NacosConstant.NACOS_CONFIG_FORMAT); |
| | | defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].data-id", NacosConstant.sharedDataId()); |
| | | defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].group", NacosConstant.NACOS_CONFIG_GROUP); |
| | | defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[0].refresh", NacosConstant.NACOS_CONFIG_REFRESH); |
| | | defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].data-id", NacosConstant.sharedDataId(profile)); |
| | | defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].group", NacosConstant.NACOS_CONFIG_GROUP); |
| | | defaultProperties.setProperty("spring.cloud.nacos.config.shared-configs[1].refresh", NacosConstant.NACOS_CONFIG_REFRESH); |
| | | builder.properties(defaultProperties); |
| | | // å è½½èªå®ä¹ç»ä»¶ |
| | | List<LauncherService> launcherList = new ArrayList<>(); |
| | | ServiceLoader.load(LauncherService.class).forEach(launcherList::add); |
| | | launcherList.stream().sorted(Comparator.comparing(LauncherService::getOrder)).collect(Collectors.toList()) |
| | | .forEach(launcherService -> launcherService.launcher(builder, appName, profile, isLocalDev())); |
| | | return builder; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸ºæ¬å°å¼åç¯å¢ |
| | | * |
| | | * @return boolean |
| | | */ |
| | | public static boolean isLocalDev() { |
| | | String osName = System.getProperty("os.name"); |
| | | return StringUtils.hasText(osName) && !(AppConstant.OS_NAME_LINUX.equalsIgnoreCase(osName)); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.web.context.WebServerInitializedEvent; |
| | | import org.springframework.context.event.EventListener; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.core.env.Environment; |
| | | import org.springframework.scheduling.annotation.Async; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | /** |
| | | * 项ç®å¯å¨äºä»¶éç¥ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AutoConfiguration |
| | | public class StartEventListener { |
| | | |
| | | @Async |
| | | @Order |
| | | @EventListener(WebServerInitializedEvent.class) |
| | | public void afterStart(WebServerInitializedEvent event) { |
| | | Environment environment = event.getApplicationContext().getEnvironment(); |
| | | String appName = environment.getProperty("spring.application.name").toUpperCase(); |
| | | int localPort = event.getWebServer().getPort(); |
| | | String profile = StringUtils.arrayToCommaDelimitedString(environment.getActiveProfiles()); |
| | | log.info("---[{}]---å¯å¨å®æï¼å½å使ç¨ç端å£:[{}]ï¼ç¯å¢åé:[{}]---", appName, localPort, profile); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.config; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.core.Ordered; |
| | | import org.springframework.core.annotation.Order; |
| | | |
| | | /** |
| | | * é
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AutoConfiguration |
| | | @AllArgsConstructor |
| | | @Order(Ordered.HIGHEST_PRECEDENCE) |
| | | public class BladeLaunchConfiguration { |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.launch.config; |
| | | |
| | | import org.springblade.core.launch.props.BladeProperties; |
| | | import org.springblade.core.launch.props.BladePropertySourcePostProcessor; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.core.Ordered; |
| | | import org.springframework.core.annotation.Order; |
| | | |
| | | /** |
| | | * blade property config |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoConfiguration |
| | | @Order(Ordered.HIGHEST_PRECEDENCE) |
| | | @EnableConfigurationProperties(BladeProperties.class) |
| | | public class BladePropertyConfiguration { |
| | | |
| | | @Bean |
| | | public BladePropertySourcePostProcessor bladePropertySourcePostProcessor() { |
| | | return new BladePropertySourcePostProcessor(); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.constant; |
| | | |
| | | /** |
| | | * ç³»ç»å¸¸é |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface AppConstant { |
| | | |
| | | /** |
| | | * åºç¨çæ¬ |
| | | */ |
| | | String APPLICATION_VERSION = "3.0.1.RELEASE"; |
| | | |
| | | /** |
| | | * åºç¡å
|
| | | */ |
| | | String BASE_PACKAGES = "org.springblade"; |
| | | |
| | | /** |
| | | * åºç¨ååç¼ |
| | | */ |
| | | String APPLICATION_NAME_PREFIX = "blade-"; |
| | | /** |
| | | * ç½å
³æ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_GATEWAY_NAME = APPLICATION_NAME_PREFIX + "gateway"; |
| | | /** |
| | | * æææ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_AUTH_NAME = APPLICATION_NAME_PREFIX + "auth"; |
| | | /** |
| | | * çæ§æ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_ADMIN_NAME = APPLICATION_NAME_PREFIX + "admin"; |
| | | /** |
| | | * æ¥è¡¨ç³»ç»åç§° |
| | | */ |
| | | String APPLICATION_REPORT_NAME = APPLICATION_NAME_PREFIX + "report"; |
| | | /** |
| | | * éç¾¤çæ§åç§° |
| | | */ |
| | | String APPLICATION_TURBINE_NAME = APPLICATION_NAME_PREFIX + "turbine"; |
| | | /** |
| | | * é¾è·¯è¿½è¸ªåç§° |
| | | */ |
| | | String APPLICATION_ZIPKIN_NAME = APPLICATION_NAME_PREFIX + "zipkin"; |
| | | /** |
| | | * websocketåç§° |
| | | */ |
| | | String APPLICATION_WEBSOCKET_NAME = APPLICATION_NAME_PREFIX + "websocket"; |
| | | /** |
| | | * é¦é¡µæ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_DESK_NAME = APPLICATION_NAME_PREFIX + "desk"; |
| | | /** |
| | | * ç³»ç»æ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_SYSTEM_NAME = APPLICATION_NAME_PREFIX + "system"; |
| | | /** |
| | | * ç¨æ·æ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_USER_NAME = APPLICATION_NAME_PREFIX + "user"; |
| | | /** |
| | | * æ¥å¿æ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_LOG_NAME = APPLICATION_NAME_PREFIX + "log"; |
| | | /** |
| | | * å¼å模ååç§° |
| | | */ |
| | | String APPLICATION_DEVELOP_NAME = APPLICATION_NAME_PREFIX + "develop"; |
| | | /** |
| | | * æµç¨è®¾è®¡å¨æ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_FLOWDESIGN_NAME = APPLICATION_NAME_PREFIX + "flowdesign"; |
| | | /** |
| | | * 工使µæ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_FLOW_NAME = APPLICATION_NAME_PREFIX + "flow"; |
| | | /** |
| | | * èµæºæ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_RESOURCE_NAME = APPLICATION_NAME_PREFIX + "resource"; |
| | | /** |
| | | * æ¥å£ææ¡£æ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_SWAGGER_NAME = APPLICATION_NAME_PREFIX + "swagger"; |
| | | /** |
| | | * æµè¯æ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_TEST_NAME = APPLICATION_NAME_PREFIX + "test"; |
| | | /** |
| | | * æ¼ç¤ºæ¨¡ååç§° |
| | | */ |
| | | String APPLICATION_DEMO_NAME = APPLICATION_NAME_PREFIX + "demo"; |
| | | |
| | | /** |
| | | * å¼åç¯å¢ |
| | | */ |
| | | String DEV_CODE = "dev"; |
| | | /** |
| | | * ç产ç¯å¢ |
| | | */ |
| | | String PROD_CODE = "prod"; |
| | | /** |
| | | * æµè¯ç¯å¢ |
| | | */ |
| | | String TEST_CODE = "test"; |
| | | |
| | | /** |
| | | * 代ç é¨ç½²äº linux ä¸ï¼å·¥ä½é»è®¤ä¸º mac å Windows |
| | | */ |
| | | String OS_NAME_LINUX = "LINUX"; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.constant; |
| | | |
| | | /** |
| | | * Consul常é. |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface ConsulConstant { |
| | | |
| | | /** |
| | | * consul dev å°å |
| | | */ |
| | | String CONSUL_HOST = "http://localhost"; |
| | | |
| | | /** |
| | | * consulç«¯å£ |
| | | */ |
| | | String CONSUL_PORT = "8500"; |
| | | |
| | | /** |
| | | * consulç«¯å£ |
| | | */ |
| | | String CONSUL_CONFIG_FORMAT = "yaml"; |
| | | |
| | | /** |
| | | * consulç«¯å£ |
| | | */ |
| | | String CONSUL_WATCH_DELAY = "1000"; |
| | | |
| | | /** |
| | | * consulç«¯å£ |
| | | */ |
| | | String CONSUL_WATCH_ENABLED = "true"; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.constant; |
| | | |
| | | /** |
| | | * æµç¨å¸¸é. |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface FlowConstant { |
| | | |
| | | /** |
| | | * ä»»å¡ç¨æ·æ è¯åç¼ |
| | | */ |
| | | String TASK_USR_PREFIX = "taskUser_"; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.constant; |
| | | |
| | | /** |
| | | * Nacos常é. |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface NacosConstant { |
| | | |
| | | /** |
| | | * nacos å°å |
| | | */ |
| | | String NACOS_ADDR = "127.0.0.1:8848"; |
| | | |
| | | /** |
| | | * nacos é
ç½®åç¼ |
| | | */ |
| | | String NACOS_CONFIG_PREFIX = "blade"; |
| | | |
| | | /** |
| | | * nacos ç»é
ç½®åç¼ |
| | | */ |
| | | String NACOS_GROUP_SUFFIX = "-group"; |
| | | |
| | | /** |
| | | * nacos é
ç½®æä»¶ç±»å |
| | | */ |
| | | String NACOS_CONFIG_FORMAT = "yaml"; |
| | | |
| | | /** |
| | | * nacos jsoné
ç½®æä»¶ç±»å |
| | | */ |
| | | String NACOS_CONFIG_JSON_FORMAT = "json"; |
| | | |
| | | /** |
| | | * nacos æ¯å¦å·æ° |
| | | */ |
| | | String NACOS_CONFIG_REFRESH = "true"; |
| | | |
| | | /** |
| | | * nacos åç» |
| | | */ |
| | | String NACOS_CONFIG_GROUP = "DEFAULT_GROUP"; |
| | | |
| | | /** |
| | | * seata åç» |
| | | */ |
| | | String NACOS_SEATA_GROUP = "SEATA_GROUP"; |
| | | |
| | | /** |
| | | * æå»ºæå¡å¯¹åºç dataId |
| | | * |
| | | * @param appName æå¡å |
| | | * @return dataId |
| | | */ |
| | | static String dataId(String appName) { |
| | | return appName + "." + NACOS_CONFIG_FORMAT; |
| | | } |
| | | |
| | | /** |
| | | * æå»ºæå¡å¯¹åºç dataId |
| | | * |
| | | * @param appName æå¡å |
| | | * @param profile ç¯å¢åé |
| | | * @return dataId |
| | | */ |
| | | static String dataId(String appName, String profile) { |
| | | return dataId(appName, profile, NACOS_CONFIG_FORMAT); |
| | | } |
| | | |
| | | /** |
| | | * æå»ºæå¡å¯¹åºç dataId |
| | | * |
| | | * @param appName æå¡å |
| | | * @param profile ç¯å¢åé |
| | | * @param format æä»¶ç±»å |
| | | * @return dataId |
| | | */ |
| | | static String dataId(String appName, String profile, String format) { |
| | | return appName + "-" + profile + "." + format; |
| | | } |
| | | |
| | | /** |
| | | * æå¡é»è®¤å è½½çé
ç½® |
| | | * |
| | | * @return sharedDataIds |
| | | */ |
| | | static String sharedDataId() { |
| | | return NACOS_CONFIG_PREFIX + "." + NACOS_CONFIG_FORMAT; |
| | | } |
| | | |
| | | /** |
| | | * æå¡é»è®¤å è½½çé
ç½® |
| | | * |
| | | * @param profile ç¯å¢åé |
| | | * @return sharedDataIds |
| | | */ |
| | | static String sharedDataId(String profile) { |
| | | return NACOS_CONFIG_PREFIX + "-" + profile + "." + NACOS_CONFIG_FORMAT; |
| | | } |
| | | |
| | | /** |
| | | * æå¡é»è®¤å è½½çé
ç½® |
| | | * |
| | | * @param profile ç¯å¢åé |
| | | * @return sharedDataIds |
| | | */ |
| | | static String sharedDataIds(String profile) { |
| | | return NACOS_CONFIG_PREFIX + "." + NACOS_CONFIG_FORMAT + "," + NACOS_CONFIG_PREFIX + "-" + profile + "." + NACOS_CONFIG_FORMAT; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.constant; |
| | | |
| | | /** |
| | | * sentinelé
ç½®. |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface SentinelConstant { |
| | | |
| | | /** |
| | | * sentinel å°å |
| | | */ |
| | | String SENTINEL_ADDR = "127.0.0.1:8858"; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.constant; |
| | | |
| | | /** |
| | | * Tokené
置常é. |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface TokenConstant { |
| | | |
| | | String AVATAR = "avatar"; |
| | | String HEADER = "Blade-Auth"; |
| | | String BEARER = "bearer"; |
| | | String ACCESS_TOKEN = "access_token"; |
| | | String REFRESH_TOKEN = "refresh_token"; |
| | | String TOKEN_TYPE = "token_type"; |
| | | String EXPIRES_IN = "expires_in"; |
| | | String ACCOUNT = "account"; |
| | | String USER_NAME = "user_name"; |
| | | String NICK_NAME = "nick_name"; |
| | | String REAL_NAME = "real_name"; |
| | | String USER_ID = "user_id"; |
| | | String DEPT_ID = "dept_id"; |
| | | String POST_ID = "post_id"; |
| | | String ROLE_ID = "role_id"; |
| | | String ROLE_NAME = "role_name"; |
| | | String TENANT_ID = "tenant_id"; |
| | | String OAUTH_ID = "oauth_id"; |
| | | String CLIENT_ID = "client_id"; |
| | | String DETAIL = "detail"; |
| | | String LICENSE = "license"; |
| | | String LICENSE_NAME = "powered by bladex"; |
| | | String DEFAULT_AVATAR = ""; |
| | | Integer AUTH_LENGTH = 7; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.constant; |
| | | |
| | | /** |
| | | * zookeeper é
ç½®. |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface ZookeeperConstant { |
| | | |
| | | /** |
| | | * zookeeper id |
| | | */ |
| | | String ZOOKEEPER_ID = "zk"; |
| | | |
| | | /** |
| | | * zookeeper connect string |
| | | */ |
| | | String ZOOKEEPER_CONNECT_STRING = "127.0.0.1:2181"; |
| | | |
| | | /** |
| | | * zookeeper address |
| | | */ |
| | | String ZOOKEEPER_ADDRESS = "zookeeper://" + ZOOKEEPER_CONNECT_STRING; |
| | | |
| | | /** |
| | | * zookeeper root |
| | | */ |
| | | String ZOOKEEPER_ROOT = "/blade-services"; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.launch.log; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.RequiredArgsConstructor; |
| | | |
| | | /** |
| | | * è¯·æ±æ¥å¿çº§å«ï¼æ¥æº okHttp |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | @RequiredArgsConstructor |
| | | public enum BladeLogLevel { |
| | | /** |
| | | * No logs. |
| | | */ |
| | | NONE(0), |
| | | |
| | | /** |
| | | * Logs request and response lines. |
| | | * |
| | | * <p>Example: |
| | | * <pre>{@code |
| | | * --> POST /greeting http/1.1 (3-byte body) |
| | | * |
| | | * <-- 200 OK (22ms, 6-byte body) |
| | | * }</pre> |
| | | */ |
| | | BASIC(1), |
| | | |
| | | /** |
| | | * Logs request and response lines and their respective headers. |
| | | * |
| | | * <p>Example: |
| | | * <pre>{@code |
| | | * --> POST /greeting http/1.1 |
| | | * Host: example.com |
| | | * Content-Type: plain/text |
| | | * Content-Length: 3 |
| | | * --> END POST |
| | | * |
| | | * <-- 200 OK (22ms) |
| | | * Content-Type: plain/text |
| | | * Content-Length: 6 |
| | | * <-- END HTTP |
| | | * }</pre> |
| | | */ |
| | | HEADERS(2), |
| | | |
| | | /** |
| | | * Logs request and response lines and their respective headers and bodies (if present). |
| | | * |
| | | * <p>Example: |
| | | * <pre>{@code |
| | | * --> POST /greeting http/1.1 |
| | | * Host: example.com |
| | | * Content-Type: plain/text |
| | | * Content-Length: 3 |
| | | * |
| | | * Hi? |
| | | * --> END POST |
| | | * |
| | | * <-- 200 OK (22ms) |
| | | * Content-Type: plain/text |
| | | * Content-Length: 6 |
| | | * |
| | | * Hello! |
| | | * <-- END HTTP |
| | | * }</pre> |
| | | */ |
| | | BODY(3); |
| | | |
| | | /** |
| | | * è¯·æ±æ¥å¿é
ç½®åç¼ |
| | | */ |
| | | public static final String REQ_LOG_PROPS_PREFIX = "blade.log.request"; |
| | | /** |
| | | * æ§å¶å°æ¥å¿æ¯å¦å¯ç¨ |
| | | */ |
| | | public static final String CONSOLE_LOG_ENABLED_PROP = "blade.log.console.enabled"; |
| | | |
| | | /** |
| | | * çº§å« |
| | | */ |
| | | private final int level; |
| | | |
| | | /** |
| | | * å½åçæ¬ å°äºåçäº æ¯è¾ççæ¬ |
| | | * |
| | | * @param level LogLevel |
| | | * @return æ¯å¦å°äºåçäº |
| | | */ |
| | | public boolean lte(BladeLogLevel level) { |
| | | return this.level <= level.level; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.props; |
| | | |
| | | import lombok.Getter; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.context.EnvironmentAware; |
| | | import org.springframework.core.env.Environment; |
| | | import org.springframework.core.env.EnvironmentCapable; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.util.Assert; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * é
ç½®æä»¶ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @ConfigurationProperties("blade") |
| | | public class BladeProperties implements EnvironmentAware, EnvironmentCapable { |
| | | @Nullable |
| | | private Environment environment; |
| | | |
| | | /** |
| | | * è£
è½½èªå®ä¹é
ç½®blade.prop.xxx |
| | | */ |
| | | @Getter |
| | | private final Map<String, String> prop = new HashMap<>(); |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @return value |
| | | */ |
| | | @Nullable |
| | | public String get(String key) { |
| | | return get(key, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return value |
| | | */ |
| | | @Nullable |
| | | public String get(String key, @Nullable String defaultValue) { |
| | | String value = prop.get(key); |
| | | if (value == null) { |
| | | return defaultValue; |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @return int value |
| | | */ |
| | | @Nullable |
| | | public Integer getInt(String key) { |
| | | return getInt(key, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return int value |
| | | */ |
| | | @Nullable |
| | | public Integer getInt(String key, @Nullable Integer defaultValue) { |
| | | String value = prop.get(key); |
| | | if (value != null) { |
| | | return Integer.valueOf(value.trim()); |
| | | } |
| | | return defaultValue; |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @return long value |
| | | */ |
| | | @Nullable |
| | | public Long getLong(String key) { |
| | | return getLong(key, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return long value |
| | | */ |
| | | @Nullable |
| | | public Long getLong(String key, @Nullable Long defaultValue) { |
| | | String value = prop.get(key); |
| | | if (value != null) { |
| | | return Long.valueOf(value.trim()); |
| | | } |
| | | return defaultValue; |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @return Boolean value |
| | | */ |
| | | @Nullable |
| | | public Boolean getBoolean(String key) { |
| | | return getBoolean(key, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return Boolean value |
| | | */ |
| | | @Nullable |
| | | public Boolean getBoolean(String key, @Nullable Boolean defaultValue) { |
| | | String value = prop.get(key); |
| | | if (value != null) { |
| | | value = value.toLowerCase().trim(); |
| | | return Boolean.parseBoolean(value); |
| | | } |
| | | return defaultValue; |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @return double value |
| | | */ |
| | | @Nullable |
| | | public Double getDouble(String key) { |
| | | return getDouble(key, null); |
| | | } |
| | | |
| | | /** |
| | | * è·åé
ç½® |
| | | * |
| | | * @param key key |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return double value |
| | | */ |
| | | @Nullable |
| | | public Double getDouble(String key, @Nullable Double defaultValue) { |
| | | String value = prop.get(key); |
| | | if (value != null) { |
| | | return Double.parseDouble(value.trim()); |
| | | } |
| | | return defaultValue; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦åå¨key |
| | | * |
| | | * @param key prop key |
| | | * @return boolean |
| | | */ |
| | | public boolean containsKey(String key) { |
| | | return prop.containsKey(key); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * ç¯å¢ï¼æ¹ä¾¿å¨ä»£ç ä¸è·å |
| | | * |
| | | * @return ç¯å¢ env |
| | | */ |
| | | public String getEnv() { |
| | | Objects.requireNonNull(environment, "Spring boot ç¯å¢ä¸ Environment ä¸å¯è½ä¸ºnull"); |
| | | String env = environment.getProperty("blade.env"); |
| | | Assert.notNull(env, "è¯·ä½¿ç¨ BladeApplication å¯å¨..."); |
| | | return env; |
| | | } |
| | | |
| | | /** |
| | | * åºç¨åç§°${spring.application.name} |
| | | * |
| | | * @return åºç¨å |
| | | */ |
| | | public String getName() { |
| | | Objects.requireNonNull(environment, "Spring boot ç¯å¢ä¸ Environment ä¸å¯è½ä¸ºnull"); |
| | | return environment.getProperty("spring.application.name", environment.getProperty("blade.name", "")); |
| | | } |
| | | |
| | | @Override |
| | | public void setEnvironment(Environment environment) { |
| | | this.environment = environment; |
| | | } |
| | | |
| | | @Override |
| | | public Environment getEnvironment() { |
| | | Objects.requireNonNull(environment, "Spring boot ç¯å¢ä¸ Environment ä¸å¯è½ä¸ºnull"); |
| | | return this.environment; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.launch.props; |
| | | |
| | | import org.springframework.core.Ordered; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * èªå®ä¹èµæºæä»¶è¯»åï¼ä¼å
级æä½ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Target(ElementType.TYPE) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | public @interface BladePropertySource { |
| | | |
| | | /** |
| | | * Indicate the resource location(s) of the properties file to be loaded. |
| | | * for example, {@code "classpath:/com/example/app.yml"} |
| | | * |
| | | * @return location(s) |
| | | */ |
| | | String value(); |
| | | |
| | | /** |
| | | * load app-{activeProfile}.yml |
| | | * |
| | | * @return {boolean} |
| | | */ |
| | | boolean loadActiveProfile() default true; |
| | | |
| | | /** |
| | | * Get the order value of this resource. |
| | | * |
| | | * @return order |
| | | */ |
| | | int order() default Ordered.LOWEST_PRECEDENCE; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.launch.props; |
| | | |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.Getter; |
| | | import lombok.ToString; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeansException; |
| | | import org.springframework.beans.factory.InitializingBean; |
| | | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; |
| | | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
| | | import org.springframework.boot.env.PropertySourceLoader; |
| | | import org.springframework.core.Ordered; |
| | | import org.springframework.core.annotation.AnnotationUtils; |
| | | import org.springframework.core.env.ConfigurableEnvironment; |
| | | import org.springframework.core.env.MutablePropertySources; |
| | | import org.springframework.core.env.PropertySource; |
| | | import org.springframework.core.io.DefaultResourceLoader; |
| | | import org.springframework.core.io.Resource; |
| | | import org.springframework.core.io.ResourceLoader; |
| | | import org.springframework.core.io.support.SpringFactoriesLoader; |
| | | import org.springframework.util.ClassUtils; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * èªå®ä¹èµæºæä»¶è¯»åï¼ä¼å
级æä½ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | public class BladePropertySourcePostProcessor implements BeanFactoryPostProcessor, InitializingBean, Ordered { |
| | | private final ResourceLoader resourceLoader; |
| | | private final List<PropertySourceLoader> propertySourceLoaders; |
| | | |
| | | public BladePropertySourcePostProcessor() { |
| | | this.resourceLoader = new DefaultResourceLoader(); |
| | | this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader()); |
| | | } |
| | | |
| | | @Override |
| | | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { |
| | | log.info("BladePropertySourcePostProcessor process @BladePropertySource bean."); |
| | | Map<String, Object> beansWithAnnotation = beanFactory.getBeansWithAnnotation(BladePropertySource.class); |
| | | Set<Map.Entry<String, Object>> beanEntrySet = beansWithAnnotation.entrySet(); |
| | | // 没æ @YmlPropertySource 注解ï¼è·³åº |
| | | if (beanEntrySet.isEmpty()) { |
| | | log.warn("Not found @BladePropertySource on spring bean class."); |
| | | return; |
| | | } |
| | | // ç»è£
èµæº |
| | | List<PropertyFile> propertyFileList = new ArrayList<>(); |
| | | for (Map.Entry<String, Object> entry : beanEntrySet) { |
| | | Class<?> beanClass = ClassUtils.getUserClass(entry.getValue()); |
| | | BladePropertySource propertySource = AnnotationUtils.getAnnotation(beanClass, BladePropertySource.class); |
| | | if (propertySource == null) { |
| | | continue; |
| | | } |
| | | int order = propertySource.order(); |
| | | boolean loadActiveProfile = propertySource.loadActiveProfile(); |
| | | String location = propertySource.value(); |
| | | propertyFileList.add(new PropertyFile(order, location, loadActiveProfile)); |
| | | } |
| | | |
| | | // è£
è½½ PropertySourceLoader |
| | | Map<String, PropertySourceLoader> loaderMap = new HashMap<>(16); |
| | | for (PropertySourceLoader loader : propertySourceLoaders) { |
| | | String[] loaderExtensions = loader.getFileExtensions(); |
| | | for (String extension : loaderExtensions) { |
| | | loaderMap.put(extension, loader); |
| | | } |
| | | } |
| | | // å»éï¼æåº |
| | | List<PropertyFile> sortedPropertyList = propertyFileList.stream() |
| | | .distinct() |
| | | .sorted() |
| | | .collect(Collectors.toList()); |
| | | ConfigurableEnvironment environment = beanFactory.getBean(ConfigurableEnvironment.class); |
| | | MutablePropertySources propertySources = environment.getPropertySources(); |
| | | |
| | | // åªæ¯æ activeProfilesï¼æ²¡æå¿
è¦æ¯æ spring.profiles.includeã |
| | | String[] activeProfiles = environment.getActiveProfiles(); |
| | | ArrayList<PropertySource> propertySourceList = new ArrayList<>(); |
| | | for (String profile : activeProfiles) { |
| | | for (PropertyFile propertyFile : sortedPropertyList) { |
| | | // ä¸å è½½ ActiveProfile çé
ç½®æä»¶ |
| | | if (!propertyFile.loadActiveProfile) { |
| | | continue; |
| | | } |
| | | String extension = propertyFile.getExtension(); |
| | | PropertySourceLoader loader = loaderMap.get(extension); |
| | | if (loader == null) { |
| | | throw new IllegalArgumentException("Can't find PropertySourceLoader for PropertySource extension:" + extension); |
| | | } |
| | | String location = propertyFile.getLocation(); |
| | | String filePath = StringUtils.stripFilenameExtension(location); |
| | | String profiledLocation = filePath + "-" + profile + "." + extension; |
| | | Resource resource = resourceLoader.getResource(profiledLocation); |
| | | loadPropertySource(profiledLocation, resource, loader, propertySourceList); |
| | | } |
| | | } |
| | | // æ¬èº«ç Resource |
| | | for (PropertyFile propertyFile : sortedPropertyList) { |
| | | String extension = propertyFile.getExtension(); |
| | | PropertySourceLoader loader = loaderMap.get(extension); |
| | | String location = propertyFile.getLocation(); |
| | | Resource resource = resourceLoader.getResource(location); |
| | | loadPropertySource(location, resource, loader, propertySourceList); |
| | | } |
| | | // 转å |
| | | for (PropertySource propertySource : propertySourceList) { |
| | | propertySources.addLast(propertySource); |
| | | } |
| | | } |
| | | |
| | | private static void loadPropertySource(String location, Resource resource, |
| | | PropertySourceLoader loader, |
| | | List<PropertySource> sourceList) { |
| | | if (resource.exists()) { |
| | | String name = "bladePropertySource: [" + location + "]"; |
| | | try { |
| | | sourceList.addAll(loader.load(name, resource)); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void afterPropertiesSet() throws Exception { |
| | | log.info("BladePropertySourcePostProcessor init."); |
| | | } |
| | | |
| | | @Override |
| | | public int getOrder() { |
| | | return Ordered.LOWEST_PRECEDENCE; |
| | | } |
| | | |
| | | @Getter |
| | | @ToString |
| | | @EqualsAndHashCode |
| | | private static class PropertyFile implements Comparable<PropertyFile> { |
| | | private final int order; |
| | | private final String location; |
| | | private final String extension; |
| | | private final boolean loadActiveProfile; |
| | | |
| | | PropertyFile(int order, String location, boolean loadActiveProfile) { |
| | | this.order = order; |
| | | this.location = location; |
| | | this.loadActiveProfile = loadActiveProfile; |
| | | this.extension = Objects.requireNonNull(StringUtils.getFilenameExtension(location)); |
| | | } |
| | | |
| | | @Override |
| | | public int compareTo(PropertyFile other) { |
| | | return Integer.compare(this.order, other.order); |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.server; |
| | | |
| | | import lombok.Getter; |
| | | import org.springblade.core.launch.utils.INetUtil; |
| | | import org.springframework.beans.factory.SmartInitializingSingleton; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.web.ServerProperties; |
| | | |
| | | /** |
| | | * æå¡å¨ä¿¡æ¯ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Getter |
| | | @AutoConfiguration |
| | | public class ServerInfo implements SmartInitializingSingleton { |
| | | private final ServerProperties serverProperties; |
| | | private String hostName; |
| | | private String ip; |
| | | private Integer port; |
| | | private String ipWithPort; |
| | | |
| | | @Autowired(required = false) |
| | | public ServerInfo(ServerProperties serverProperties) { |
| | | this.serverProperties = serverProperties; |
| | | } |
| | | |
| | | @Override |
| | | public void afterSingletonsInstantiated() { |
| | | this.hostName = INetUtil.getHostName(); |
| | | this.ip = INetUtil.getHostIp(); |
| | | this.port = serverProperties.getPort(); |
| | | this.ipWithPort = String.format("%s:%d", ip, port); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.service; |
| | | |
| | | import org.springframework.boot.builder.SpringApplicationBuilder; |
| | | import org.springframework.core.Ordered; |
| | | |
| | | /** |
| | | * launcher æ©å± ç¨äºä¸äºç»ä»¶åç° |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface LauncherService extends Ordered, Comparable<LauncherService> { |
| | | |
| | | /** |
| | | * å¯å¨æ¶ å¤ç SpringApplicationBuilder |
| | | * |
| | | * @param builder SpringApplicationBuilder |
| | | * @param appName SpringApplicationAppName |
| | | * @param profile SpringApplicationProfile |
| | | * @param isLocalDev SpringApplicationIsLocalDev |
| | | */ |
| | | void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev); |
| | | |
| | | /** |
| | | * è·åæåé¡ºåº |
| | | * |
| | | * @return order |
| | | */ |
| | | @Override |
| | | default int getOrder() { |
| | | return 0; |
| | | } |
| | | |
| | | /** |
| | | * å¯¹æ¯æåº |
| | | * |
| | | * @param o LauncherService |
| | | * @return compare |
| | | */ |
| | | @Override |
| | | default int compareTo(LauncherService o) { |
| | | return Integer.compare(this.getOrder(), o.getOrder()); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.launch.utils; |
| | | |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.net.NetworkInterface; |
| | | import java.net.ServerSocket; |
| | | import java.net.UnknownHostException; |
| | | import java.util.Enumeration; |
| | | |
| | | /** |
| | | * INet ç¸å
³å·¥å
· |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class INetUtil { |
| | | public static final String LOCAL_HOST = "127.0.0.1"; |
| | | |
| | | /** |
| | | * è·å æå¡å¨ hostname |
| | | * |
| | | * @return hostname |
| | | */ |
| | | public static String getHostName() { |
| | | String hostname; |
| | | try { |
| | | InetAddress address = InetAddress.getLocalHost(); |
| | | // force a best effort reverse DNS lookup |
| | | hostname = address.getHostName(); |
| | | if (StringUtils.isEmpty(hostname)) { |
| | | hostname = address.toString(); |
| | | } |
| | | } catch (UnknownHostException ignore) { |
| | | hostname = LOCAL_HOST; |
| | | } |
| | | return hostname; |
| | | } |
| | | |
| | | /** |
| | | * è·å æå¡å¨ HostIp |
| | | * |
| | | * @return HostIp |
| | | */ |
| | | public static String getHostIp() { |
| | | String hostAddress; |
| | | try { |
| | | InetAddress address = INetUtil.getLocalHostLANAddress(); |
| | | // force a best effort reverse DNS lookup |
| | | hostAddress = address.getHostAddress(); |
| | | if (StringUtils.isEmpty(hostAddress)) { |
| | | hostAddress = address.toString(); |
| | | } |
| | | } catch (UnknownHostException ignore) { |
| | | hostAddress = LOCAL_HOST; |
| | | } |
| | | return hostAddress; |
| | | } |
| | | |
| | | /** |
| | | * https://stackoverflow.com/questions/9481865/getting-the-ip-address-of-the-current-machine-using-java |
| | | * |
| | | * <p> |
| | | * Returns an <code>InetAddress</code> object encapsulating what is most likely the machine's LAN IP address. |
| | | * <p/> |
| | | * This method is intended for use as a replacement of JDK method <code>InetAddress.getLocalHost</code>, because |
| | | * that method is ambiguous on Linux systems. Linux systems enumerate the loopback network interface the same |
| | | * way as regular LAN network interfaces, but the JDK <code>InetAddress.getLocalHost</code> method does not |
| | | * specify the algorithm used to select the address returned under such circumstances, and will often return the |
| | | * loopback address, which is not valid for network communication. Details |
| | | * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4665037">here</a>. |
| | | * <p/> |
| | | * This method will scan all IP addresses on all network interfaces on the host machine to determine the IP address |
| | | * most likely to be the machine's LAN address. If the machine has multiple IP addresses, this method will prefer |
| | | * a site-local IP address (e.g. 192.168.x.x or 10.10.x.x, usually IPv4) if the machine has one (and will return the |
| | | * first site-local address if the machine has more than one), but if the machine does not hold a site-local |
| | | * address, this method will return simply the first non-loopback address found (IPv4 or IPv6). |
| | | * <p/> |
| | | * If this method cannot find a non-loopback address using this selection algorithm, it will fall back to |
| | | * calling and returning the result of JDK method <code>InetAddress.getLocalHost</code>. |
| | | * <p/> |
| | | * |
| | | * @throws UnknownHostException If the LAN address of the machine cannot be found. |
| | | */ |
| | | private static InetAddress getLocalHostLANAddress() throws UnknownHostException { |
| | | try { |
| | | InetAddress candidateAddress = null; |
| | | // Iterate all NICs (network interface cards)... |
| | | for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) { |
| | | NetworkInterface iface = (NetworkInterface) ifaces.nextElement(); |
| | | // Iterate all IP addresses assigned to each card... |
| | | for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) { |
| | | InetAddress inetAddr = (InetAddress) inetAddrs.nextElement(); |
| | | if (!inetAddr.isLoopbackAddress()) { |
| | | |
| | | if (inetAddr.isSiteLocalAddress()) { |
| | | // Found non-loopback site-local address. Return it immediately... |
| | | return inetAddr; |
| | | } else if (candidateAddress == null) { |
| | | // Found non-loopback address, but not necessarily site-local. |
| | | // Store it as a candidate to be returned if site-local address is not subsequently found... |
| | | candidateAddress = inetAddr; |
| | | // Note that we don't repeatedly assign non-loopback non-site-local addresses as candidates, |
| | | // only the first. For subsequent iterations, candidate will be non-null. |
| | | } |
| | | } |
| | | } |
| | | } |
| | | if (candidateAddress != null) { |
| | | // We did not find a site-local address, but we found some other non-loopback address. |
| | | // Server might have a non-site-local address assigned to its NIC (or it might be running |
| | | // IPv6 which deprecates the "site-local" concept). |
| | | // Return this non-loopback candidate address... |
| | | return candidateAddress; |
| | | } |
| | | // At this point, we did not find a non-loopback address. |
| | | // Fall back to returning whatever InetAddress.getLocalHost() returns... |
| | | InetAddress jdkSuppliedAddress = InetAddress.getLocalHost(); |
| | | if (jdkSuppliedAddress == null) { |
| | | throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null."); |
| | | } |
| | | return jdkSuppliedAddress; |
| | | } catch (Exception e) { |
| | | UnknownHostException unknownHostException = new UnknownHostException("Failed to determine LAN address: " + e); |
| | | unknownHostException.initCause(e); |
| | | throw unknownHostException; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°è¯ç«¯å£æ¶å被å ç¨ |
| | | * |
| | | * @param port 端å£å· |
| | | * @return 没æè¢«å ç¨ï¼true,被å ç¨ï¼false |
| | | */ |
| | | public static boolean tryPort(int port) { |
| | | try (ServerSocket ignore = new ServerSocket(port)) { |
| | | return true; |
| | | } catch (Exception e) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å° ip 转æ InetAddress |
| | | * |
| | | * @param ip ip |
| | | * @return InetAddress |
| | | */ |
| | | public static InetAddress getInetAddress(String ip) { |
| | | try { |
| | | return InetAddress.getByName(ip); |
| | | } catch (UnknownHostException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦å
ç½ ip |
| | | * |
| | | * @param ip ip |
| | | * @return boolean |
| | | */ |
| | | public static boolean isInternalIp(String ip) { |
| | | return isInternalIp(getInetAddress(ip)); |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦å
ç½ ip |
| | | * |
| | | * @param address InetAddress |
| | | * @return boolean |
| | | */ |
| | | public static boolean isInternalIp(InetAddress address) { |
| | | if (isLocalIp(address)) { |
| | | return true; |
| | | } |
| | | return isInternalIp(address.getAddress()); |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦æ¬å° ip |
| | | * |
| | | * @param address InetAddress |
| | | * @return boolean |
| | | */ |
| | | public static boolean isLocalIp(InetAddress address) { |
| | | return address.isAnyLocalAddress() |
| | | || address.isLoopbackAddress() |
| | | || address.isSiteLocalAddress(); |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦å
ç½ ip |
| | | * |
| | | * @param addr ip |
| | | * @return boolean |
| | | */ |
| | | public static boolean isInternalIp(byte[] addr) { |
| | | final byte b0 = addr[0]; |
| | | final byte b1 = addr[1]; |
| | | //10.x.x.x/8 |
| | | final byte section1 = 0x0A; |
| | | //172.16.x.x/12 |
| | | final byte section2 = (byte) 0xAC; |
| | | final byte section3 = (byte) 0x10; |
| | | final byte section4 = (byte) 0x1F; |
| | | //192.168.x.x/16 |
| | | final byte section5 = (byte) 0xC0; |
| | | final byte section6 = (byte) 0xA8; |
| | | switch (b0) { |
| | | case section1: |
| | | return true; |
| | | case section2: |
| | | if (b1 >= section3 && b1 <= section4) { |
| | | return true; |
| | | } |
| | | case section5: |
| | | if (b1 == section6) { |
| | | return true; |
| | | } |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.launch.utils; |
| | | |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.util.Properties; |
| | | |
| | | /** |
| | | * é
置工å
·ç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class PropsUtil { |
| | | |
| | | /** |
| | | * 设置é
ç½®å¼ï¼å·²åå¨åè·³è¿ |
| | | * |
| | | * @param props property |
| | | * @param key key |
| | | * @param value value |
| | | */ |
| | | public static void setProperty(Properties props, String key, String value) { |
| | | if (StringUtils.isEmpty(props.getProperty(key))) { |
| | | props.setProperty(key, value); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | |
| | | <parent> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <groupId>org.springblade</groupId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-log4j2</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-launch</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-log4j2</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.lmax</groupId> |
| | | <artifactId>disruptor</artifactId> |
| | | </dependency> |
| | | <!-- Auto --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.log4j2; |
| | | |
| | | import org.springblade.core.auto.service.AutoService; |
| | | import org.springblade.core.launch.service.LauncherService; |
| | | import org.springframework.boot.builder.SpringApplicationBuilder; |
| | | |
| | | /** |
| | | * æ¥å¿å¯å¨å¨ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoService(LauncherService.class) |
| | | public class LogLauncherServiceImpl implements LauncherService { |
| | | |
| | | @Override |
| | | public void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev) { |
| | | System.setProperty("logging.config", String.format("classpath:log/log4j2_%s.xml", profile)); |
| | | // RocketMQ-Client 4.2.0 Log4j2 é
ç½®æä»¶å²çªé®é¢è§£å³ï¼https://www.jianshu.com/p/b30ae6dd3811 |
| | | System.setProperty("rocketmq.client.log.loadconfig", "false"); |
| | | // RocketMQ-Client 4.3 设置é»è®¤ä¸º slf4j |
| | | System.setProperty("rocketmq.client.logUseSlf4j", "true"); |
| | | // éæ¬å° å° å
¨é¨ç System.err å System.out æ¿æ¢ä¸ºlog |
| | | if (!isLocalDev) { |
| | | System.setOut(LogPrintStream.out()); |
| | | System.setErr(LogPrintStream.err()); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.log4j2; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.io.PrintStream; |
| | | import java.util.Locale; |
| | | |
| | | /** |
| | | * æ¿æ¢ ç³»ç» System.err å System.out 为log |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | public class LogPrintStream extends PrintStream { |
| | | private final boolean error; |
| | | |
| | | private LogPrintStream(boolean error) { |
| | | super(error ? System.err : System.out); |
| | | this.error = error; |
| | | } |
| | | |
| | | public static LogPrintStream out() { |
| | | return new LogPrintStream(false); |
| | | } |
| | | |
| | | public static LogPrintStream err() { |
| | | return new LogPrintStream(true); |
| | | } |
| | | |
| | | @Override |
| | | public void print(String s) { |
| | | if (error) { |
| | | log.error(s); |
| | | } else { |
| | | log.info(s); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * éåæå®ï¼å 为å®ä¼æå°å¾å¤æ ç¨çæ°è¡ |
| | | */ |
| | | @Override |
| | | public void println() { |
| | | } |
| | | |
| | | @Override |
| | | public void println(String x) { |
| | | if (error) { |
| | | log.error(x); |
| | | } else { |
| | | log.info(x); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public PrintStream printf(String format, Object... args) { |
| | | if (error) { |
| | | log.error(String.format(format, args)); |
| | | } else { |
| | | log.info(String.format(format, args)); |
| | | } |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public PrintStream printf(Locale l, String format, Object... args) { |
| | | if (error) { |
| | | log.error(String.format(l, format, args)); |
| | | } else { |
| | | log.info(String.format(l, format, args)); |
| | | } |
| | | return this; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <Appenders> |
| | | <Console name="Console" target="SYSTEM_OUT" follow="true"> |
| | | <PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}"/> |
| | | </Console> |
| | | <RollingFile name="RollingFile" |
| | | fileName="${logdir}/${appName}.log" |
| | | filePattern="${logdir}/${appName}.%d{yyyy-MM-dd}.%i.log.gz"> |
| | | <PatternLayout pattern="[%d] [%thread] ${LOG_LEVEL_PATTERN} ${appName} ${sys:PID} %c %m%n"/> |
| | | <Filters> |
| | | <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL" /> |
| | | <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY" /> |
| | | </Filters> |
| | | <Policies> |
| | | <SizeBasedTriggeringPolicy size="200MB" /> |
| | | <TimeBasedTriggeringPolicy modulate="true" interval="1"/> |
| | | </Policies> |
| | | <DefaultRolloverStrategy max="30"/> |
| | | </RollingFile> |
| | | <!-- åªæ¾ç¤ºerror级å«çä¿¡æ¯ --> |
| | | <RollingFile name="RollingFileError" |
| | | fileName="${logdir}/${appName}-error.log" |
| | | filePattern="${logdir}/${appName}-error.%d{yyyy-MM-dd}.%i.log.gz"> |
| | | <PatternLayout pattern="[%d] [%thread] ${LOG_LEVEL_PATTERN} ${appName} ${sys:PID} %c %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}"/> |
| | | <Filters> |
| | | <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> |
| | | </Filters> |
| | | <Policies> |
| | | <SizeBasedTriggeringPolicy size="200MB"/> |
| | | <TimeBasedTriggeringPolicy modulate="true" interval="1"/> |
| | | </Policies> |
| | | <DefaultRolloverStrategy max="30"/> |
| | | </RollingFile> |
| | | </Appenders> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <configuration status="off" xmlns:xi="http://www.w3.org/2001/XInclude"> |
| | | <Properties> |
| | | <Property name="appName">${sys:spring.application.name}</Property> |
| | | <Property name="logdir">${env:LOG_BASE:-logs}/${appName}</Property> |
| | | <Property name="PID">????</Property> |
| | | <Property name="LOG_LEVEL_PATTERN">%5p</Property> |
| | | <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property> |
| | | <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property> |
| | | <Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%C{36}.%M:%L}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> |
| | | </Properties> |
| | | <xi:include href="log4j2_appenders.xml"> |
| | | <xi:fallback/> |
| | | </xi:include> |
| | | <Loggers> |
| | | <!-- åå°é¨ådebugæ¥å¿ --> |
| | | <AsyncLogger name="org.springframework.context" level="WARN"/> |
| | | <AsyncLogger name="org.springframework.beans" level="WARN"/> |
| | | <AsyncLogger name="springfox.bean.validators" level="ERROR"/> |
| | | <!-- åºç¡ç»ä»¶ --> |
| | | <AsyncLogger name="RocketmqClient" level="WARN"/> |
| | | <!-- mongo no sql --> |
| | | <AsyncLogger name="org.springframework.data.mongodb.core" level="DEBUG"/> |
| | | <!-- bladeæ¥å¿ --> |
| | | <AsyncLogger name="org.springblade.core" level="INFO"/> |
| | | <Root level="INFO" additivity="false"> |
| | | <AppenderRef ref="Console"/> |
| | | <AppenderRef ref="RollingFile"/> |
| | | <AppenderRef ref="RollingFileError"/> |
| | | </Root> |
| | | </Loggers> |
| | | </configuration> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <configuration status="off" xmlns:xi="http://www.w3.org/2001/XInclude"> |
| | | <Properties> |
| | | <Property name="appName">${sys:spring.application.name}</Property> |
| | | <Property name="logdir">${env:LOG_BASE:-logs}/${appName}</Property> |
| | | <Property name="PID">????</Property> |
| | | <Property name="LOG_LEVEL_PATTERN">%5p</Property> |
| | | <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property> |
| | | <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property> |
| | | <Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> |
| | | </Properties> |
| | | <xi:include href="log4j2_appenders.xml"> |
| | | <xi:fallback/> |
| | | </xi:include> |
| | | <Loggers> |
| | | <!-- åå°é¨ådebugæ¥å¿ --> |
| | | <AsyncLogger name="org.springframework.context" level="WARN"/> |
| | | <AsyncLogger name="org.springframework.beans" level="WARN"/> |
| | | <AsyncLogger name="springfox.bean.validators" level="ERROR"/> |
| | | <!-- åºç¡ç»ä»¶ --> |
| | | <AsyncLogger name="RocketmqClient" level="WARN"/> |
| | | <!-- bladeæ¥å¿ --> |
| | | <AsyncLogger name="org.springblade.core" level="WARN" /> |
| | | <AsyncLogger name="org.springblade.core.http" level="INFO"/> |
| | | <Root level="INFO" additivity="false"> |
| | | <AppenderRef ref="Console"/> |
| | | <AppenderRef ref="RollingFile"/> |
| | | <AppenderRef ref="RollingFileError"/> |
| | | </Root> |
| | | </Loggers> |
| | | </configuration> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <configuration status="off" xmlns:xi="http://www.w3.org/2001/XInclude"> |
| | | <Properties> |
| | | <Property name="appName">${sys:spring.application.name}</Property> |
| | | <Property name="logdir">${env:LOG_BASE:-logs}/${appName}</Property> |
| | | <Property name="PID">????</Property> |
| | | <Property name="LOG_LEVEL_PATTERN">%5p</Property> |
| | | <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property> |
| | | <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property> |
| | | <Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> |
| | | </Properties> |
| | | <xi:include href="log4j2_appenders.xml"> |
| | | <xi:fallback/> |
| | | </xi:include> |
| | | <Loggers> |
| | | <!-- åå°é¨ådebugæ¥å¿ --> |
| | | <AsyncLogger name="springfox.bean.validators" level="ERROR"/> |
| | | <!-- åºç¡ç»ä»¶ --> |
| | | <AsyncLogger name="RocketmqClient" level="ERROR"/> |
| | | <!-- bladeæ¥å¿ --> |
| | | <AsyncLogger name="org.springblade.core" level="ERROR"/> |
| | | <AsyncLogger name="org.springblade.core.http" level="INFO"/> |
| | | <Root level="WARN" additivity="false"> |
| | | <AppenderRef ref="Console" /> |
| | | <AppenderRef ref="RollingFile" /> |
| | | <AppenderRef ref="RollingFileError" /> |
| | | </Root> |
| | | </Loggers> |
| | | </configuration> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <configuration status="off" xmlns:xi="http://www.w3.org/2001/XInclude"> |
| | | <Properties> |
| | | <Property name="appName">${sys:spring.application.name}</Property> |
| | | <Property name="logdir">${env:LOG_BASE:-logs}/${appName}</Property> |
| | | <Property name="PID">????</Property> |
| | | <Property name="LOG_LEVEL_PATTERN">%5p</Property> |
| | | <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property> |
| | | <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property> |
| | | <Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%C{36}.%M:%L}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property> |
| | | </Properties> |
| | | <xi:include href="log4j2_appenders.xml"> |
| | | <xi:fallback/> |
| | | </xi:include> |
| | | <Loggers> |
| | | <!-- åå°é¨ådebugæ¥å¿ --> |
| | | <AsyncLogger name="org.springframework.context" level="WARN"/> |
| | | <AsyncLogger name="org.springframework.beans" level="WARN"/> |
| | | <AsyncLogger name="springfox.bean.validators" level="ERROR"/> |
| | | <!-- åºç¡ç»ä»¶ --> |
| | | <AsyncLogger name="RocketmqClient" level="WARN"/> |
| | | <!-- bladeæ¥å¿ --> |
| | | <AsyncLogger name="org.springblade.core" level="INFO"/> |
| | | <Root level="INFO" additivity="false"> |
| | | <AppenderRef ref="Console"/> |
| | | <AppenderRef ref="RollingFile"/> |
| | | <AppenderRef ref="RollingFileError"/> |
| | | </Root> |
| | | </Loggers> |
| | | </configuration> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <groupId>org.springblade</groupId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-secure</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <dependencies> |
| | | <!--Blade--> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-auth</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-starter-cache</artifactId> |
| | | </dependency> |
| | | <!--Jdbc--> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-jdbc</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>tomcat-jdbc</artifactId> |
| | | <groupId>org.apache.tomcat</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <!-- Auto --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.annotation; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * æé注解 ç¨äºæ£æ¥æé è§å®è®¿é®æé |
| | | * |
| | | * @example @PreAuth("#userVO.id<10") |
| | | * @example @PreAuth("hasRole(#test, #test1)") |
| | | * @example @PreAuth("hasPermission(#test) and @PreAuth.hasPermission(#test)") |
| | | * @author Chill |
| | | */ |
| | | @Target({ElementType.METHOD, ElementType.TYPE}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Inherited |
| | | @Documented |
| | | public @interface PreAuth { |
| | | |
| | | /** |
| | | * Spring el |
| | | * ææ¡£å°åï¼https://docs.spring.io/spring/docs/5.1.6.RELEASE/spring-framework-reference/core.html#expressions |
| | | */ |
| | | String value(); |
| | | |
| | | } |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.aspect; |
| | | |
| | | import org.aspectj.lang.ProceedingJoinPoint; |
| | | import org.aspectj.lang.annotation.Around; |
| | | import org.aspectj.lang.annotation.Aspect; |
| | | import org.aspectj.lang.reflect.MethodSignature; |
| | | import org.springblade.core.secure.annotation.PreAuth; |
| | | import org.springblade.core.secure.auth.AuthFun; |
| | | import org.springblade.core.secure.exception.SecureException; |
| | | import org.springblade.core.tool.api.ResultCode; |
| | | import org.springblade.core.tool.utils.ClassUtil; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springframework.beans.BeansException; |
| | | import org.springframework.context.ApplicationContext; |
| | | import org.springframework.context.ApplicationContextAware; |
| | | import org.springframework.context.expression.BeanFactoryResolver; |
| | | import org.springframework.core.MethodParameter; |
| | | import org.springframework.expression.Expression; |
| | | import org.springframework.expression.ExpressionParser; |
| | | import org.springframework.expression.spel.standard.SpelExpressionParser; |
| | | import org.springframework.expression.spel.support.StandardEvaluationContext; |
| | | import org.springframework.lang.NonNull; |
| | | |
| | | import java.lang.reflect.Method; |
| | | |
| | | /** |
| | | * AOP é´æ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Aspect |
| | | public class AuthAspect implements ApplicationContextAware { |
| | | |
| | | /** |
| | | * 表达å¼å¤ç |
| | | */ |
| | | private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); |
| | | |
| | | /** |
| | | * å æ¹æ³ å ç±»ä¸ç @PreAuth 注解 |
| | | * |
| | | * @param point åç¹ |
| | | * @return Object |
| | | * @throws Throwable 没ææéçå¼å¸¸ |
| | | */ |
| | | @Around( |
| | | "@annotation(org.springblade.core.secure.annotation.PreAuth) || " + |
| | | "@within(org.springblade.core.secure.annotation.PreAuth)" |
| | | ) |
| | | public Object preAuth(ProceedingJoinPoint point) throws Throwable { |
| | | if (handleAuth(point)) { |
| | | return point.proceed(); |
| | | } |
| | | throw new SecureException(ResultCode.UN_AUTHORIZED); |
| | | } |
| | | |
| | | /** |
| | | * å¤çæé |
| | | * |
| | | * @param point åç¹ |
| | | */ |
| | | private boolean handleAuth(ProceedingJoinPoint point) { |
| | | MethodSignature ms = (MethodSignature) point.getSignature(); |
| | | Method method = ms.getMethod(); |
| | | // 读åæé注解ï¼ä¼å
æ¹æ³ä¸ï¼æ²¡æå读åç±» |
| | | PreAuth preAuth = ClassUtil.getAnnotation(method, PreAuth.class); |
| | | // å¤æè¡¨è¾¾å¼ |
| | | String condition = preAuth.value(); |
| | | if (StringUtil.isNotBlank(condition)) { |
| | | Expression expression = EXPRESSION_PARSER.parseExpression(condition); |
| | | // æ¹æ³åæ°å¼ |
| | | Object[] args = point.getArgs(); |
| | | StandardEvaluationContext context = getEvaluationContext(method, args); |
| | | return expression.getValue(context, Boolean.class); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * è·åæ¹æ³ä¸çåæ° |
| | | * |
| | | * @param method æ¹æ³ |
| | | * @param args åé |
| | | * @return {SimpleEvaluationContext} |
| | | */ |
| | | private StandardEvaluationContext getEvaluationContext(Method method, Object[] args) { |
| | | // åå§åSp el表达å¼ä¸ä¸æï¼å¹¶è®¾ç½® AuthFun |
| | | StandardEvaluationContext context = new StandardEvaluationContext(new AuthFun()); |
| | | // è®¾ç½®è¡¨è¾¾å¼æ¯æspring bean |
| | | context.setBeanResolver(new BeanFactoryResolver(applicationContext)); |
| | | for (int i = 0; i < args.length; i++) { |
| | | // è¯»åæ¹æ³åæ° |
| | | MethodParameter methodParam = ClassUtil.getMethodParameter(method, i); |
| | | // è®¾ç½®æ¹æ³ åæ°ååå¼ ä¸ºsp elåé |
| | | context.setVariable(methodParam.getParameterName(), args[i]); |
| | | } |
| | | return context; |
| | | } |
| | | |
| | | private ApplicationContext applicationContext; |
| | | |
| | | @Override |
| | | public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { |
| | | this.applicationContext = applicationContext; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.auth; |
| | | |
| | | import org.springblade.core.secure.BladeUser; |
| | | import org.springblade.core.secure.handler.IPermissionHandler; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springblade.core.tool.constant.RoleConstant; |
| | | import org.springblade.core.tool.utils.*; |
| | | |
| | | /** |
| | | * æé夿 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class AuthFun { |
| | | |
| | | /** |
| | | * æéæ ¡éªå¤çå¨ |
| | | */ |
| | | private static IPermissionHandler permissionHandler; |
| | | |
| | | private static IPermissionHandler getPermissionHandler() { |
| | | if (permissionHandler == null) { |
| | | permissionHandler = SpringUtil.getBean(IPermissionHandler.class); |
| | | } |
| | | return permissionHandler; |
| | | } |
| | | |
| | | /** |
| | | * 夿è§è²æ¯å¦å
·ææ¥å£æé |
| | | * |
| | | * @return {boolean} |
| | | */ |
| | | public boolean permissionAll() { |
| | | return getPermissionHandler().permissionAll(); |
| | | } |
| | | |
| | | /** |
| | | * 夿è§è²æ¯å¦å
·ææ¥å£æé |
| | | * |
| | | * @param permission æéç¼å· |
| | | * @return {boolean} |
| | | */ |
| | | public boolean hasPermission(String permission) { |
| | | return getPermissionHandler().hasPermission(permission); |
| | | } |
| | | |
| | | /** |
| | | * æ¾è¡ææè¯·æ± |
| | | * |
| | | * @return {boolean} |
| | | */ |
| | | public boolean permitAll() { |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * åªæè¶
管è§è²æå¯è®¿é® |
| | | * |
| | | * @return {boolean} |
| | | */ |
| | | public boolean denyAll() { |
| | | return hasRole(RoleConstant.ADMIN); |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦å·²ææ |
| | | * |
| | | * @return {boolean} |
| | | */ |
| | | public boolean hasAuth() { |
| | | return Func.isNotEmpty(AuthUtil.getUser()); |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦ææ¶é´ææ |
| | | * |
| | | * @param start å¼å§æ¶é´ |
| | | * @param end ç»ææ¶é´ |
| | | * @return {boolean} |
| | | */ |
| | | public boolean hasTimeAuth(Integer start, Integer end) { |
| | | Integer hour = DateUtil.hour(); |
| | | return hour >= start && hour <= end; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦æè¯¥è§è²æé |
| | | * |
| | | * @param role åè§è² |
| | | * @return {boolean} |
| | | */ |
| | | public boolean hasRole(String role) { |
| | | return hasAnyRole(role); |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦å
·æææè§è²æé |
| | | * |
| | | * @param role è§è²éå |
| | | * @return {boolean} |
| | | */ |
| | | public boolean hasAllRole(String... role) { |
| | | for (String r : role) { |
| | | if (!hasRole(r)) { |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦æè¯¥è§è²æé |
| | | * |
| | | * @param role è§è²éå |
| | | * @return {boolean} |
| | | */ |
| | | public boolean hasAnyRole(String... role) { |
| | | BladeUser user = AuthUtil.getUser(); |
| | | if (user == null) { |
| | | return false; |
| | | } |
| | | String userRole = user.getRoleName(); |
| | | if (StringUtil.isBlank(userRole)) { |
| | | return false; |
| | | } |
| | | String[] roles = Func.toStrArray(userRole); |
| | | for (String r : role) { |
| | | if (CollectionUtil.contains(roles, r)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.config; |
| | | |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springblade.core.secure.handler.BladePermissionHandler; |
| | | import org.springblade.core.secure.handler.IPermissionHandler; |
| | | import org.springblade.core.secure.handler.ISecureHandler; |
| | | import org.springblade.core.secure.handler.SecureHandlerHandler; |
| | | import org.springblade.core.secure.registry.SecureRegistry; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | /** |
| | | * secure注åé»è®¤é
ç½® |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Order |
| | | @AutoConfiguration(before = SecureConfiguration.class) |
| | | @AllArgsConstructor |
| | | public class RegistryConfiguration { |
| | | |
| | | private final JdbcTemplate jdbcTemplate; |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean(SecureRegistry.class) |
| | | public SecureRegistry secureRegistry() { |
| | | return new SecureRegistry(); |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean(ISecureHandler.class) |
| | | public ISecureHandler secureHandler() { |
| | | return new SecureHandlerHandler(); |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean(IPermissionHandler.class) |
| | | public IPermissionHandler permissionHandler() { |
| | | return new BladePermissionHandler(jdbcTemplate); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.config; |
| | | |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springblade.core.secure.aspect.AuthAspect; |
| | | import org.springblade.core.secure.handler.ISecureHandler; |
| | | import org.springblade.core.secure.props.AuthSecure; |
| | | import org.springblade.core.secure.props.BasicSecure; |
| | | import org.springblade.core.secure.props.BladeSecureProperties; |
| | | import org.springblade.core.secure.props.SignSecure; |
| | | import org.springblade.core.secure.provider.ClientDetailsServiceImpl; |
| | | import org.springblade.core.secure.provider.IClientDetailsService; |
| | | import org.springblade.core.secure.registry.SecureRegistry; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
| | | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
| | | |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * å®å
¨é
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Order |
| | | @AutoConfiguration |
| | | @AllArgsConstructor |
| | | @EnableConfigurationProperties({BladeSecureProperties.class}) |
| | | public class SecureConfiguration implements WebMvcConfigurer { |
| | | |
| | | private final SecureRegistry secureRegistry; |
| | | |
| | | private final BladeSecureProperties secureProperties; |
| | | |
| | | private final JdbcTemplate jdbcTemplate; |
| | | |
| | | private final ISecureHandler secureHandler; |
| | | |
| | | @Override |
| | | public void addInterceptors(@NonNull InterceptorRegistry registry) { |
| | | // è®¾ç½®è¯·æ±ææ |
| | | if (secureRegistry.isAuthEnabled() || secureProperties.getAuthEnabled()) { |
| | | List<AuthSecure> authSecures = this.secureRegistry.addAuthPatterns(secureProperties.getAuth()).getAuthSecures(); |
| | | if (authSecures.size() > 0) { |
| | | registry.addInterceptor(secureHandler.authInterceptor(authSecures)); |
| | | // è®¾ç½®è·¯å¾æ¾è¡ |
| | | secureRegistry.excludePathPatterns(authSecures.stream().map(AuthSecure::getPattern).collect(Collectors.toList())); |
| | | } |
| | | } |
| | | // 设置åºç¡è®¤è¯ææ |
| | | if (secureRegistry.isBasicEnabled() || secureProperties.getBasicEnabled()) { |
| | | List<BasicSecure> basicSecures = this.secureRegistry.addBasicPatterns(secureProperties.getBasic()).getBasicSecures(); |
| | | if (basicSecures.size() > 0) { |
| | | registry.addInterceptor(secureHandler.basicInterceptor(basicSecures)); |
| | | // è®¾ç½®è·¯å¾æ¾è¡ |
| | | secureRegistry.excludePathPatterns(basicSecures.stream().map(BasicSecure::getPattern).collect(Collectors.toList())); |
| | | } |
| | | } |
| | | // 设置ç¾åè®¤è¯ææ |
| | | if (secureRegistry.isSignEnabled() || secureProperties.getSignEnabled()) { |
| | | List<SignSecure> signSecures = this.secureRegistry.addSignPatterns(secureProperties.getSign()).getSignSecures(); |
| | | if (signSecures.size() > 0) { |
| | | registry.addInterceptor(secureHandler.signInterceptor(signSecures)); |
| | | // è®¾ç½®è·¯å¾æ¾è¡ |
| | | secureRegistry.excludePathPatterns(signSecures.stream().map(SignSecure::getPattern).collect(Collectors.toList())); |
| | | } |
| | | } |
| | | // 设置客æ·ç«¯ææ |
| | | if (secureRegistry.isClientEnabled() || secureProperties.getClientEnabled()) { |
| | | secureProperties.getClient().forEach( |
| | | clientSecure -> registry.addInterceptor(secureHandler.clientInterceptor(clientSecure.getClientId())) |
| | | .addPathPatterns(clientSecure.getPathPatterns()) |
| | | ); |
| | | } |
| | | // è®¾ç½®è·¯å¾æ¾è¡ |
| | | if (secureRegistry.isEnabled() || secureProperties.getEnabled()) { |
| | | registry.addInterceptor(secureHandler.tokenInterceptor()) |
| | | .excludePathPatterns(secureRegistry.getExcludePatterns()) |
| | | .excludePathPatterns(secureRegistry.getDefaultExcludePatterns()) |
| | | .excludePathPatterns(secureProperties.getSkipUrl()); |
| | | } |
| | | } |
| | | |
| | | @Bean |
| | | public AuthAspect authAspect() { |
| | | return new AuthAspect(); |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean(IClientDetailsService.class) |
| | | public IClientDetailsService clientDetailsService() { |
| | | return new ClientDetailsServiceImpl(jdbcTemplate); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.constant; |
| | | |
| | | /** |
| | | * PreAuthæéè¡¨è¾¾å¼ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface AuthConstant { |
| | | |
| | | /** |
| | | * è¶
管å«å |
| | | */ |
| | | String ADMINISTRATOR = "administrator"; |
| | | |
| | | /** |
| | | * æ¯æè¶
管è§è² |
| | | */ |
| | | String HAS_ROLE_ADMINISTRATOR = "hasRole('" + ADMINISTRATOR + "')"; |
| | | |
| | | /** |
| | | * 管çåå«å |
| | | */ |
| | | String ADMIN = "admin"; |
| | | |
| | | /** |
| | | * æ¯å¦æç®¡çåè§è² |
| | | */ |
| | | String HAS_ROLE_ADMIN = "hasAnyRole('" + ADMINISTRATOR + "', '" + ADMIN + "')"; |
| | | |
| | | /** |
| | | * ç¨æ·å«å |
| | | */ |
| | | String USER = "user"; |
| | | |
| | | /** |
| | | * æ¯å¦æç¨æ·è§è² |
| | | */ |
| | | String HAS_ROLE_USER = "hasRole('" + USER + "')"; |
| | | |
| | | /** |
| | | * æµè¯å«å |
| | | */ |
| | | String TEST = "test"; |
| | | |
| | | /** |
| | | * æ¯å¦ææµè¯è§è² |
| | | */ |
| | | String HAS_ROLE_TEST = "hasRole('" + TEST + "')"; |
| | | |
| | | /** |
| | | * æ¾è¡ææè¯·æ± |
| | | */ |
| | | String PERMIT_ALL = "permitAll()"; |
| | | |
| | | /** |
| | | * åªæè¶
管æè½è®¿é® |
| | | */ |
| | | String DENY_ALL = "denyAll()"; |
| | | |
| | | /** |
| | | * 对ææè¯·æ±è¿è¡æ¥å£æéæ ¡éª |
| | | */ |
| | | String PERMISSION_ALL = "permissionAll()"; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.constant; |
| | | |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | |
| | | /** |
| | | * æéæ ¡éªå¸¸é |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface PermissionConstant { |
| | | |
| | | /** |
| | | * è·åè§è²ææçæéç¼å· |
| | | * |
| | | * @param size æ°é |
| | | * @return string |
| | | */ |
| | | static String permissionAllStatement(int size) { |
| | | return "select scope_path as path from blade_scope_api where id in (select scope_id from blade_role_scope where scope_category = 2 and role_id in (" + buildHolder(size) + "))"; |
| | | } |
| | | |
| | | /** |
| | | * è·åè§è²æå®çæéç¼å· |
| | | * |
| | | * @param size æ°é |
| | | * @return string |
| | | */ |
| | | static String permissionStatement(int size) { |
| | | return "select resource_code as code from blade_scope_api where resource_code = ? and id in (select scope_id from blade_role_scope where scope_category = 2 and role_id in (" + buildHolder(size) + "))"; |
| | | } |
| | | |
| | | /** |
| | | * è·åSqlå ä½ç¬¦ |
| | | * |
| | | * @param size æ°é |
| | | * @return String |
| | | */ |
| | | static String buildHolder(int size) { |
| | | StringBuilder builder = StringUtil.builder(); |
| | | for (int i = 0; i < size; i++) { |
| | | builder.append("?,"); |
| | | } |
| | | return StringUtil.removeSuffix(builder.toString(), ","); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.constant; |
| | | |
| | | /** |
| | | * æææ ¡éªå¸¸é |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface SecureConstant { |
| | | |
| | | /** |
| | | * 认è¯è¯·æ±å¤´ |
| | | */ |
| | | String BASIC_HEADER_KEY = "Authorization"; |
| | | |
| | | /** |
| | | * 认è¯è¯·æ±å¤´åç¼ |
| | | */ |
| | | String BASIC_HEADER_PREFIX = "Basic "; |
| | | |
| | | /** |
| | | * 认è¯è¯·æ±å¤´åç¼ |
| | | */ |
| | | String BASIC_HEADER_PREFIX_EXT = "Basic%20"; |
| | | |
| | | /** |
| | | * 认è¯è¯·æ±å¤´ |
| | | */ |
| | | String BASIC_REALM_HEADER_KEY = "WWW-Authenticate"; |
| | | |
| | | /** |
| | | * 认è¯è¯·æ±å¼ |
| | | */ |
| | | String BASIC_REALM_HEADER_VALUE = "basic realm=\"no auth\""; |
| | | |
| | | /** |
| | | * blade_clientè¡¨åæ®µ |
| | | */ |
| | | String CLIENT_FIELDS = "client_id, client_secret, access_token_validity, refresh_token_validity"; |
| | | |
| | | /** |
| | | * blade_clientæ¥è¯¢è¯å¥ |
| | | */ |
| | | String BASE_STATEMENT = "select " + CLIENT_FIELDS + " from blade_client"; |
| | | |
| | | /** |
| | | * blade_clientæ¥è¯¢æåº |
| | | */ |
| | | String DEFAULT_FIND_STATEMENT = BASE_STATEMENT + " order by client_id"; |
| | | |
| | | /** |
| | | * æ¥è¯¢client_id |
| | | */ |
| | | String DEFAULT_SELECT_STATEMENT = BASE_STATEMENT + " where client_id = ?"; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.handler; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springblade.core.cache.utils.CacheUtil; |
| | | import org.springblade.core.secure.BladeUser; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springblade.core.tool.utils.Func; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | |
| | | import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE; |
| | | import static org.springblade.core.secure.constant.PermissionConstant.permissionAllStatement; |
| | | import static org.springblade.core.secure.constant.PermissionConstant.permissionStatement; |
| | | |
| | | /** |
| | | * é»è®¤æææ ¡éªç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AllArgsConstructor |
| | | public class BladePermissionHandler implements IPermissionHandler { |
| | | |
| | | private static final String SCOPE_CACHE_CODE = "apiScope:code:"; |
| | | |
| | | private final JdbcTemplate jdbcTemplate; |
| | | |
| | | @Override |
| | | public boolean permissionAll() { |
| | | HttpServletRequest request = WebUtil.getRequest(); |
| | | BladeUser user = AuthUtil.getUser(); |
| | | if (request == null || user == null) { |
| | | return false; |
| | | } |
| | | String uri = request.getRequestURI(); |
| | | List<String> paths = permissionPath(user.getRoleId()); |
| | | if (paths.size() == 0) { |
| | | return false; |
| | | } |
| | | return paths.stream().anyMatch(uri::contains); |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasPermission(String permission) { |
| | | HttpServletRequest request = WebUtil.getRequest(); |
| | | BladeUser user = AuthUtil.getUser(); |
| | | if (request == null || user == null) { |
| | | return false; |
| | | } |
| | | List<String> codes = permissionCode(permission, user.getRoleId()); |
| | | return codes.size() != 0; |
| | | } |
| | | |
| | | /** |
| | | * è·åæ¥å£æéå°å |
| | | * |
| | | * @param roleId è§è²id |
| | | * @return permissions |
| | | */ |
| | | private List<String> permissionPath(String roleId) { |
| | | List<String> permissions = CacheUtil.get(SYS_CACHE, SCOPE_CACHE_CODE, roleId, List.class, Boolean.FALSE); |
| | | if (permissions == null) { |
| | | List<Long> roleIds = Func.toLongList(roleId); |
| | | permissions = jdbcTemplate.queryForList(permissionAllStatement(roleIds.size()), roleIds.toArray(), String.class); |
| | | CacheUtil.put(SYS_CACHE, SCOPE_CACHE_CODE, roleId, permissions, Boolean.FALSE); |
| | | } |
| | | return permissions; |
| | | } |
| | | |
| | | /** |
| | | * è·åæ¥å£æéä¿¡æ¯ |
| | | * |
| | | * @param permission æéç¼å· |
| | | * @param roleId è§è²id |
| | | * @return permissions |
| | | */ |
| | | private List<String> permissionCode(String permission, String roleId) { |
| | | List<String> permissions = CacheUtil.get(SYS_CACHE, SCOPE_CACHE_CODE, permission + StringPool.COLON + roleId, List.class, Boolean.FALSE); |
| | | if (permissions == null) { |
| | | List<Object> args = new ArrayList<>(Collections.singletonList(permission)); |
| | | List<Long> roleIds = Func.toLongList(roleId); |
| | | args.addAll(roleIds); |
| | | permissions = jdbcTemplate.queryForList(permissionStatement(roleIds.size()), args.toArray(), String.class); |
| | | CacheUtil.put(SYS_CACHE, SCOPE_CACHE_CODE, permission + StringPool.COLON + roleId, permissions, Boolean.FALSE); |
| | | } |
| | | return permissions; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.handler; |
| | | |
| | | /** |
| | | * æéæ ¡éªéç¨æ¥å£ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface IPermissionHandler { |
| | | |
| | | /** |
| | | * 夿è§è²æ¯å¦å
·ææ¥å£æé |
| | | * |
| | | * @return {boolean} |
| | | */ |
| | | boolean permissionAll(); |
| | | |
| | | /** |
| | | * 夿è§è²æ¯å¦å
·ææ¥å£æé |
| | | * |
| | | * @param permission æéç¼å· |
| | | * @return {boolean} |
| | | */ |
| | | boolean hasPermission(String permission); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.handler; |
| | | |
| | | import org.springblade.core.secure.props.AuthSecure; |
| | | import org.springblade.core.secure.props.BasicSecure; |
| | | import org.springblade.core.secure.props.SignSecure; |
| | | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * secure æ¦æªå¨éå |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface ISecureHandler { |
| | | |
| | | /** |
| | | * tokenæ¦æªå¨ |
| | | * |
| | | * @return tokenInterceptor |
| | | */ |
| | | HandlerInterceptorAdapter tokenInterceptor(); |
| | | |
| | | /** |
| | | * authæ¦æªå¨ |
| | | * |
| | | * @param authSecures ææéå |
| | | * @return HandlerInterceptorAdapter |
| | | */ |
| | | HandlerInterceptorAdapter authInterceptor(List<AuthSecure> authSecures); |
| | | |
| | | /** |
| | | * basicæ¦æªå¨ |
| | | * |
| | | * @param basicSecures åºç¡è®¤è¯éå |
| | | * @return HandlerInterceptorAdapter |
| | | */ |
| | | HandlerInterceptorAdapter basicInterceptor(List<BasicSecure> basicSecures); |
| | | |
| | | /** |
| | | * signæ¦æªå¨ |
| | | * |
| | | * @param signSecures ç¾å认è¯éå |
| | | * @return HandlerInterceptorAdapter |
| | | */ |
| | | HandlerInterceptorAdapter signInterceptor(List<SignSecure> signSecures); |
| | | |
| | | /** |
| | | * clientæ¦æªå¨ |
| | | * |
| | | * @param clientId 客æ·ç«¯id |
| | | * @return clientInterceptor |
| | | */ |
| | | HandlerInterceptorAdapter clientInterceptor(String clientId); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.handler; |
| | | |
| | | import org.springblade.core.secure.interceptor.*; |
| | | import org.springblade.core.secure.props.AuthSecure; |
| | | import org.springblade.core.secure.props.BasicSecure; |
| | | import org.springblade.core.secure.props.SignSecure; |
| | | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Secureå¤çå¨ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class SecureHandlerHandler implements ISecureHandler { |
| | | |
| | | @Override |
| | | public HandlerInterceptorAdapter tokenInterceptor() { |
| | | return new TokenInterceptor(); |
| | | } |
| | | |
| | | @Override |
| | | public HandlerInterceptorAdapter authInterceptor(List<AuthSecure> authSecures) { |
| | | return new AuthInterceptor(authSecures); |
| | | } |
| | | |
| | | @Override |
| | | public HandlerInterceptorAdapter basicInterceptor(List<BasicSecure> basicSecures) { |
| | | return new BasicInterceptor(basicSecures); |
| | | } |
| | | |
| | | @Override |
| | | public HandlerInterceptorAdapter signInterceptor(List<SignSecure> signSecures) { |
| | | return new SignInterceptor(signSecures); |
| | | } |
| | | |
| | | @Override |
| | | public HandlerInterceptorAdapter clientInterceptor(String clientId) { |
| | | return new ClientInterceptor(clientId); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.interceptor; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.secure.auth.AuthFun; |
| | | import org.springblade.core.secure.props.AuthSecure; |
| | | import org.springblade.core.secure.provider.HttpMethod; |
| | | import org.springblade.core.secure.provider.ResponseProvider; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.expression.EvaluationContext; |
| | | import org.springframework.expression.ExpressionParser; |
| | | import org.springframework.expression.spel.standard.SpelExpressionParser; |
| | | import org.springframework.expression.spel.support.StandardEvaluationContext; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.util.AntPathMatcher; |
| | | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * èªå®ä¹æææ¦æªå¨æ ¡éª |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AllArgsConstructor |
| | | public class AuthInterceptor extends HandlerInterceptorAdapter { |
| | | |
| | | /** |
| | | * 表达å¼å¤ç |
| | | */ |
| | | private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); |
| | | private static final EvaluationContext EVALUATION_CONTEXT = new StandardEvaluationContext(new AuthFun()); |
| | | private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher(); |
| | | |
| | | /** |
| | | * ææéå |
| | | */ |
| | | private final List<AuthSecure> authSecures; |
| | | |
| | | @Override |
| | | public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) { |
| | | boolean check = authSecures.stream().filter(authSecure -> checkAuth(request, authSecure)).findFirst().map( |
| | | authSecure -> checkExpression(authSecure.getExpression()) |
| | | ).orElse(Boolean.TRUE); |
| | | if (!check) { |
| | | log.warn("ææè®¤è¯å¤±è´¥ï¼è¯·æ±æ¥å£ï¼{}ï¼è¯·æ±IPï¼{}ï¼è¯·æ±åæ°ï¼{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap())); |
| | | ResponseProvider.write(response); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * æ£æµææ |
| | | */ |
| | | private boolean checkAuth(HttpServletRequest request, AuthSecure authSecure) { |
| | | return checkMethod(request, authSecure.getMethod()) && checkPath(request, authSecure.getPattern()); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè¯·æ±æ¹æ³ |
| | | */ |
| | | private boolean checkMethod(HttpServletRequest request, HttpMethod method) { |
| | | return method == HttpMethod.ALL || ( |
| | | method != null && method == HttpMethod.of(request.getMethod()) |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè·¯å¾å¹é
|
| | | */ |
| | | private boolean checkPath(HttpServletRequest request, String pattern) { |
| | | String servletPath = request.getServletPath(); |
| | | String pathInfo = request.getPathInfo(); |
| | | if (pathInfo != null && pathInfo.length() > 0) { |
| | | servletPath = servletPath + pathInfo; |
| | | } |
| | | return ANT_PATH_MATCHER.match(pattern, servletPath); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè¡¨è¾¾å¼ |
| | | */ |
| | | private boolean checkExpression(String expression) { |
| | | Boolean result = EXPRESSION_PARSER.parseExpression(expression).getValue(EVALUATION_CONTEXT, Boolean.class); |
| | | return result != null ? result : false; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.interceptor; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.secure.props.BasicSecure; |
| | | import org.springblade.core.secure.provider.HttpMethod; |
| | | import org.springblade.core.secure.provider.ResponseProvider; |
| | | import org.springblade.core.secure.utils.SecureUtil; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.util.AntPathMatcher; |
| | | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.List; |
| | | |
| | | import static org.springblade.core.secure.constant.SecureConstant.BASIC_REALM_HEADER_KEY; |
| | | import static org.springblade.core.secure.constant.SecureConstant.BASIC_REALM_HEADER_VALUE; |
| | | |
| | | /** |
| | | * åºç¡è®¤è¯æ¦æªå¨æ ¡éª |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AllArgsConstructor |
| | | public class BasicInterceptor extends HandlerInterceptorAdapter { |
| | | |
| | | /** |
| | | * 表达å¼å¹é
|
| | | */ |
| | | private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher(); |
| | | |
| | | /** |
| | | * ææéå |
| | | */ |
| | | private final List<BasicSecure> basicSecures; |
| | | |
| | | @Override |
| | | public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) { |
| | | boolean check = basicSecures.stream().filter(basicSecure -> checkAuth(request, basicSecure)).findFirst().map( |
| | | authSecure -> checkBasic(authSecure.getUsername(), authSecure.getPassword()) |
| | | ).orElse(Boolean.TRUE); |
| | | if (!check) { |
| | | log.warn("ææè®¤è¯å¤±è´¥ï¼è¯·æ±æ¥å£ï¼{}ï¼è¯·æ±IPï¼{}ï¼è¯·æ±åæ°ï¼{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap())); |
| | | response.setHeader(BASIC_REALM_HEADER_KEY, BASIC_REALM_HEADER_VALUE); |
| | | ResponseProvider.write(response); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * æ£æµææ |
| | | */ |
| | | private boolean checkAuth(HttpServletRequest request, BasicSecure basicSecure) { |
| | | return checkMethod(request, basicSecure.getMethod()) && checkPath(request, basicSecure.getPattern()); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè¯·æ±æ¹æ³ |
| | | */ |
| | | private boolean checkMethod(HttpServletRequest request, HttpMethod method) { |
| | | return method == HttpMethod.ALL || ( |
| | | method != null && method == HttpMethod.of(request.getMethod()) |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè·¯å¾å¹é
|
| | | */ |
| | | private boolean checkPath(HttpServletRequest request, String pattern) { |
| | | String servletPath = request.getServletPath(); |
| | | String pathInfo = request.getPathInfo(); |
| | | if (pathInfo != null && pathInfo.length() > 0) { |
| | | servletPath = servletPath + pathInfo; |
| | | } |
| | | return ANT_PATH_MATCHER.match(pattern, servletPath); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè¡¨è¾¾å¼ |
| | | */ |
| | | private boolean checkBasic(String username, String password) { |
| | | try { |
| | | String[] tokens = SecureUtil.extractAndDecodeHeader(); |
| | | return username.equals(tokens[0]) && password.equals(tokens[1]); |
| | | } catch (Exception e) { |
| | | log.warn("ææè®¤è¯å¤±è´¥ï¼é误信æ¯ï¼{}", e.getMessage()); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.interceptor; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.secure.BladeUser; |
| | | import org.springblade.core.secure.provider.ResponseProvider; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springblade.core.secure.utils.SecureUtil; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | /** |
| | | * 客æ·ç«¯æ ¡éªæ¦æªå¨ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AllArgsConstructor |
| | | public class ClientInterceptor extends HandlerInterceptorAdapter { |
| | | |
| | | private final String clientId; |
| | | |
| | | @Override |
| | | public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) { |
| | | BladeUser user = AuthUtil.getUser(); |
| | | boolean check = ( |
| | | user != null && |
| | | StringUtil.equals(clientId, SecureUtil.getClientIdFromHeader()) && |
| | | StringUtil.equals(clientId, user.getClientId()) |
| | | ); |
| | | if (!check) { |
| | | log.warn("客æ·ç«¯è®¤è¯å¤±è´¥ï¼è¯·æ±æ¥å£ï¼{}ï¼è¯·æ±IPï¼{}ï¼è¯·æ±åæ°ï¼{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap())); |
| | | ResponseProvider.write(response); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.interceptor; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.secure.props.SignSecure; |
| | | import org.springblade.core.secure.provider.HttpMethod; |
| | | import org.springblade.core.secure.provider.ResponseProvider; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springblade.core.tool.utils.DateUtil; |
| | | import org.springblade.core.tool.utils.DigestUtil; |
| | | import org.springblade.core.tool.utils.Func; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.util.AntPathMatcher; |
| | | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.time.Duration; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * ç¾åè®¤è¯æ¦æªå¨æ ¡éª |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AllArgsConstructor |
| | | public class SignInterceptor extends HandlerInterceptorAdapter { |
| | | |
| | | /** |
| | | * 表达å¼å¹é
|
| | | */ |
| | | private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher(); |
| | | |
| | | /** |
| | | * ææéå |
| | | */ |
| | | private final List<SignSecure> signSecures; |
| | | |
| | | /** |
| | | * è¯·æ±æ¶é´ |
| | | */ |
| | | private final static String TIMESTAMP = "timestamp"; |
| | | |
| | | /** |
| | | * éæºæ° |
| | | */ |
| | | private final static String NONCE = "nonce"; |
| | | |
| | | /** |
| | | * æ¶é´éæºæ°ç»åå å¯ä¸² |
| | | */ |
| | | private final static String SIGNATURE = "signature"; |
| | | |
| | | /** |
| | | * sha1å 坿¹å¼ |
| | | */ |
| | | private final static String SHA1 = "sha1"; |
| | | |
| | | /** |
| | | * md5å 坿¹å¼ |
| | | */ |
| | | private final static String MD5 = "md5"; |
| | | |
| | | /** |
| | | * æ¶é´å·®æå°å¼ |
| | | */ |
| | | private final static Integer SECOND_MIN = 0; |
| | | |
| | | /** |
| | | * æ¶é´å·®æå¤§å¼ |
| | | */ |
| | | private final static Integer SECOND_MAX = 10; |
| | | |
| | | @Override |
| | | public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) { |
| | | boolean check = signSecures.stream().filter(signSecure -> checkAuth(request, signSecure)).findFirst().map( |
| | | authSecure -> checkSign(authSecure.getCrypto()) |
| | | ).orElse(Boolean.TRUE); |
| | | if (!check) { |
| | | log.warn("ææè®¤è¯å¤±è´¥ï¼è¯·æ±æ¥å£ï¼{}ï¼è¯·æ±IPï¼{}ï¼è¯·æ±åæ°ï¼{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap())); |
| | | ResponseProvider.write(response); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * æ£æµææ |
| | | */ |
| | | private boolean checkAuth(HttpServletRequest request, SignSecure signSecure) { |
| | | return checkMethod(request, signSecure.getMethod()) && checkPath(request, signSecure.getPattern()); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè¯·æ±æ¹æ³ |
| | | */ |
| | | private boolean checkMethod(HttpServletRequest request, HttpMethod method) { |
| | | return method == HttpMethod.ALL || ( |
| | | method != null && method == HttpMethod.of(request.getMethod()) |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè·¯å¾å¹é
|
| | | */ |
| | | private boolean checkPath(HttpServletRequest request, String pattern) { |
| | | String servletPath = request.getServletPath(); |
| | | String pathInfo = request.getPathInfo(); |
| | | if (pathInfo != null && pathInfo.length() > 0) { |
| | | servletPath = servletPath + pathInfo; |
| | | } |
| | | return ANT_PATH_MATCHER.match(pattern, servletPath); |
| | | } |
| | | |
| | | /** |
| | | * æ£æµè¡¨è¾¾å¼ |
| | | */ |
| | | private boolean checkSign(String crypto) { |
| | | try { |
| | | HttpServletRequest request = WebUtil.getRequest(); |
| | | if (request == null) { |
| | | return false; |
| | | } |
| | | // è·å头é¨å¨æç¾åä¿¡æ¯ |
| | | String timestamp = request.getHeader(TIMESTAMP); |
| | | // 夿æ¯å¦å¨åæ³æ¶é´æ®µ |
| | | long seconds = Duration.between(new Date(Func.toLong(timestamp)).toInstant(), DateUtil.now().toInstant()).getSeconds(); |
| | | if (seconds < SECOND_MIN || seconds > SECOND_MAX) { |
| | | log.warn("ææè®¤è¯å¤±è´¥ï¼é误信æ¯ï¼{}", "è¯·æ±æ¶é´æ³éæ³"); |
| | | return false; |
| | | } |
| | | String nonce = request.getHeader(NONCE); |
| | | String signature = request.getHeader(SIGNATURE); |
| | | // å å¯ç¾åæ¯å¯¹ï¼å¯èªè¡æå±å å¯è§å |
| | | String sign; |
| | | if (crypto.equals(MD5)) { |
| | | sign = DigestUtil.md5Hex(timestamp + nonce); |
| | | } else if (crypto.equals(SHA1)) { |
| | | sign = DigestUtil.sha1Hex(timestamp + nonce); |
| | | } else { |
| | | sign = DigestUtil.sha1Hex(timestamp + nonce); |
| | | } |
| | | return sign.equalsIgnoreCase(signature); |
| | | } catch (Exception e) { |
| | | log.warn("ææè®¤è¯å¤±è´¥ï¼é误信æ¯ï¼{}", e.getMessage()); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.interceptor; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.secure.provider.ResponseProvider; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springblade.core.tool.utils.WebUtil; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | /** |
| | | * ç¾åè®¤è¯æ¦æªå¨ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | @AllArgsConstructor |
| | | public class TokenInterceptor extends HandlerInterceptorAdapter { |
| | | |
| | | @Override |
| | | public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) { |
| | | if (null == AuthUtil.getUser()) { |
| | | log.warn("ç¾å认è¯å¤±è´¥ï¼è¯·æ±æ¥å£ï¼{}ï¼è¯·æ±IPï¼{}ï¼è¯·æ±åæ°ï¼{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap())); |
| | | ResponseProvider.write(response); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.props; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | import org.springblade.core.secure.provider.HttpMethod; |
| | | |
| | | /** |
| | | * èªå®ä¹ææè§å |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class AuthSecure { |
| | | |
| | | /** |
| | | * è¯·æ±æ¹æ³ |
| | | */ |
| | | private HttpMethod method; |
| | | /** |
| | | * 请æ±è·¯å¾ |
| | | */ |
| | | private String pattern; |
| | | /** |
| | | * è§åè¡¨è¾¾å¼ |
| | | */ |
| | | private String expression; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.props; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | import org.springblade.core.secure.provider.HttpMethod; |
| | | |
| | | /** |
| | | * åºç¡ææè§å |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class BasicSecure { |
| | | |
| | | /** |
| | | * è¯·æ±æ¹æ³ |
| | | */ |
| | | private HttpMethod method; |
| | | /** |
| | | * 请æ±è·¯å¾ |
| | | */ |
| | | private String pattern; |
| | | /** |
| | | * 客æ·ç«¯id |
| | | */ |
| | | private String username; |
| | | /** |
| | | * 客æ·ç«¯å¯é¥ |
| | | */ |
| | | private String password; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.props; |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 客æ·ç«¯æ ¡éªé
ç½® |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | @ConfigurationProperties("blade.secure") |
| | | public class BladeSecureProperties { |
| | | |
| | | /** |
| | | * å¼å¯é´æè§å |
| | | */ |
| | | private Boolean enabled = false; |
| | | |
| | | /** |
| | | * é´ææ¾è¡è¯·æ± |
| | | */ |
| | | private final List<String> skipUrl = new ArrayList<>(); |
| | | |
| | | /** |
| | | * å¼å¯ææè§å |
| | | */ |
| | | private Boolean authEnabled = true; |
| | | |
| | | /** |
| | | * ææé
ç½® |
| | | */ |
| | | private final List<AuthSecure> auth = new ArrayList<>(); |
| | | |
| | | /** |
| | | * å¼å¯åºç¡è®¤è¯è§å |
| | | */ |
| | | private Boolean basicEnabled = true; |
| | | |
| | | /** |
| | | * åºç¡è®¤è¯é
ç½® |
| | | */ |
| | | private final List<BasicSecure> basic = new ArrayList<>(); |
| | | |
| | | /** |
| | | * å¼å¯ç¾å认è¯è§å |
| | | */ |
| | | private Boolean signEnabled = true; |
| | | |
| | | /** |
| | | * ç¾å认è¯é
ç½® |
| | | */ |
| | | private final List<SignSecure> sign = new ArrayList<>(); |
| | | |
| | | /** |
| | | * å¼å¯å®¢æ·ç«¯è§å |
| | | */ |
| | | private Boolean clientEnabled = true; |
| | | |
| | | /** |
| | | * 客æ·ç«¯é
ç½® |
| | | */ |
| | | private final List<ClientSecure> client = new ArrayList<>(); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.props; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 客æ·ç«¯ä»¤ç认è¯ä¿¡æ¯ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | public class ClientSecure { |
| | | |
| | | /** |
| | | * 客æ·ç«¯ID |
| | | */ |
| | | private String clientId; |
| | | /** |
| | | * è·¯å¾å¹é
|
| | | */ |
| | | private final List<String> pathPatterns = new ArrayList<>(); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.props; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | import org.springblade.core.secure.provider.HttpMethod; |
| | | |
| | | /** |
| | | * ç¾åææè§å |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class SignSecure { |
| | | |
| | | /** |
| | | * è¯·æ±æ¹æ³ |
| | | */ |
| | | private HttpMethod method; |
| | | /** |
| | | * 请æ±è·¯å¾ |
| | | */ |
| | | private String pattern; |
| | | /** |
| | | * å 坿¹å¼ |
| | | */ |
| | | private String crypto; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.provider; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 客æ·ç«¯è¯¦æ
|
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | public class ClientDetails implements IClientDetails { |
| | | |
| | | /** |
| | | * 客æ·ç«¯id |
| | | */ |
| | | @ApiModelProperty(value = "客æ·ç«¯id") |
| | | private String clientId; |
| | | /** |
| | | * 客æ·ç«¯å¯é¥ |
| | | */ |
| | | @ApiModelProperty(value = "客æ·ç«¯å¯é¥") |
| | | private String clientSecret; |
| | | |
| | | /** |
| | | * 令çè¿æç§æ° |
| | | */ |
| | | @ApiModelProperty(value = "令çè¿æç§æ°") |
| | | private Integer accessTokenValidity; |
| | | /** |
| | | * å·æ°ä»¤çè¿æç§æ° |
| | | */ |
| | | @ApiModelProperty(value = "å·æ°ä»¤çè¿æç§æ°") |
| | | private Integer refreshTokenValidity; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.provider; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springblade.core.secure.constant.SecureConstant; |
| | | import org.springframework.jdbc.core.BeanPropertyRowMapper; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | /** |
| | | * è·å客æ·ç«¯è¯¦æ
|
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AllArgsConstructor |
| | | public class ClientDetailsServiceImpl implements IClientDetailsService { |
| | | |
| | | private final JdbcTemplate jdbcTemplate; |
| | | |
| | | @Override |
| | | public IClientDetails loadClientByClientId(String clientId) { |
| | | try { |
| | | return jdbcTemplate.queryForObject(SecureConstant.DEFAULT_SELECT_STATEMENT, new String[]{clientId}, new BeanPropertyRowMapper<>(ClientDetails.class)); |
| | | } catch (Exception ex) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.provider; |
| | | |
| | | /** |
| | | * HttpMethodæä¸¾ç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public enum HttpMethod { |
| | | |
| | | /** |
| | | * è¯·æ±æ¹æ³éå |
| | | */ |
| | | GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, ALL; |
| | | |
| | | /** |
| | | * å¹é
æä¸¾ |
| | | */ |
| | | public static HttpMethod of(String method) { |
| | | try { |
| | | return valueOf(method); |
| | | } catch (Exception exception) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.provider; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * å¤ç»ç«¯è¯¦æ
æ¥å£ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface IClientDetails extends Serializable { |
| | | |
| | | /** |
| | | * 客æ·ç«¯id. |
| | | * |
| | | * @return String. |
| | | */ |
| | | String getClientId(); |
| | | |
| | | /** |
| | | * 客æ·ç«¯å¯é¥. |
| | | * |
| | | * @return String. |
| | | */ |
| | | String getClientSecret(); |
| | | |
| | | /** |
| | | * 客æ·ç«¯tokenè¿ææ¶é´ |
| | | * |
| | | * @return Integer |
| | | */ |
| | | Integer getAccessTokenValidity(); |
| | | |
| | | /** |
| | | * 客æ·ç«¯å·æ°tokenè¿ææ¶é´ |
| | | * |
| | | * @return Integer |
| | | */ |
| | | Integer getRefreshTokenValidity(); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.provider; |
| | | |
| | | /** |
| | | * å¤ç»ç«¯æ³¨åæ¥å£ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface IClientDetailsService { |
| | | |
| | | /** |
| | | * æ ¹æ®clientIdè·åClient详æ
|
| | | * |
| | | * @param clientId 客æ·ç«¯id |
| | | * @return |
| | | */ |
| | | IClientDetails loadClientByClientId(String clientId); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.provider; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.api.ResultCode; |
| | | import org.springblade.core.tool.constant.BladeConstant; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springframework.http.MediaType; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * ResponseProvider |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | public class ResponseProvider { |
| | | |
| | | public static void write(HttpServletResponse response) { |
| | | R result = R.fail(ResultCode.UN_AUTHORIZED); |
| | | response.setCharacterEncoding(BladeConstant.UTF_8); |
| | | response.addHeader(BladeConstant.CONTENT_TYPE_NAME, MediaType.APPLICATION_JSON_VALUE); |
| | | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); |
| | | try { |
| | | response.getWriter().write(Objects.requireNonNull(JsonUtil.toJson(result))); |
| | | } catch (IOException ex) { |
| | | log.error(ex.getMessage()); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.registry; |
| | | |
| | | import lombok.Data; |
| | | import org.springblade.core.secure.props.AuthSecure; |
| | | import org.springblade.core.secure.props.BasicSecure; |
| | | import org.springblade.core.secure.props.SignSecure; |
| | | import org.springblade.core.secure.provider.HttpMethod; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å®å
¨æ¡æ¶ç»ä¸é
ç½® |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | public class SecureRegistry { |
| | | |
| | | /** |
| | | * æ¯å¦å¼å¯é´æ |
| | | */ |
| | | private boolean enabled = false; |
| | | |
| | | /** |
| | | * æ¯å¦å¼å¯ææ |
| | | */ |
| | | private boolean authEnabled = true; |
| | | |
| | | /** |
| | | * æ¯å¦å¼å¯åºç¡è®¤è¯ |
| | | */ |
| | | private boolean basicEnabled = true; |
| | | |
| | | /** |
| | | * æ¯å¦å¼å¯ç¾åè®¤è¯ |
| | | */ |
| | | private boolean signEnabled = true; |
| | | |
| | | /** |
| | | * æ¯å¦å¼å¯å®¢æ·ç«¯è®¤è¯ |
| | | */ |
| | | private boolean clientEnabled = true; |
| | | |
| | | /** |
| | | * é»è®¤æ¾è¡è§å |
| | | */ |
| | | private final List<String> defaultExcludePatterns = new ArrayList<>(); |
| | | |
| | | /** |
| | | * èªå®ä¹æ¾è¡è§å |
| | | */ |
| | | private final List<String> excludePatterns = new ArrayList<>(); |
| | | |
| | | /** |
| | | * èªå®ä¹ææéå |
| | | */ |
| | | private final List<AuthSecure> authSecures = new ArrayList<>(); |
| | | |
| | | /** |
| | | * åºç¡è®¤è¯éå |
| | | */ |
| | | private final List<BasicSecure> basicSecures = new ArrayList<>(); |
| | | |
| | | /** |
| | | * ç¾å认è¯éå |
| | | */ |
| | | private final List<SignSecure> signSecures = new ArrayList<>(); |
| | | |
| | | public SecureRegistry() { |
| | | this.defaultExcludePatterns.add("/actuator/health/**"); |
| | | this.defaultExcludePatterns.add("/v2/api-docs/**"); |
| | | this.defaultExcludePatterns.add("/auth/**"); |
| | | this.defaultExcludePatterns.add("/token/**"); |
| | | this.defaultExcludePatterns.add("/log/**"); |
| | | this.defaultExcludePatterns.add("/menu/routes"); |
| | | this.defaultExcludePatterns.add("/menu/auth-routes"); |
| | | this.defaultExcludePatterns.add("/menu/top-menu"); |
| | | this.defaultExcludePatterns.add("/process/resource-view"); |
| | | this.defaultExcludePatterns.add("/process/diagram-view"); |
| | | this.defaultExcludePatterns.add("/manager/check-upload"); |
| | | this.defaultExcludePatterns.add("/error/**"); |
| | | this.defaultExcludePatterns.add("/assets/**"); |
| | | } |
| | | |
| | | /** |
| | | * 设置å个æ¾è¡api |
| | | */ |
| | | public SecureRegistry excludePathPattern(String pattern) { |
| | | this.excludePatterns.add(pattern); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置æ¾è¡apiéå |
| | | */ |
| | | public SecureRegistry excludePathPatterns(String... patterns) { |
| | | this.excludePatterns.addAll(Arrays.asList(patterns)); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置æ¾è¡apiéå |
| | | */ |
| | | public SecureRegistry excludePathPatterns(List<String> patterns) { |
| | | this.excludePatterns.addAll(patterns); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置å个èªå®ä¹ææ |
| | | */ |
| | | public SecureRegistry addAuthPattern(HttpMethod method, String pattern, String expression) { |
| | | this.authSecures.add(new AuthSecure(method, pattern, expression)); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置èªå®ä¹ææéå |
| | | */ |
| | | public SecureRegistry addAuthPatterns(List<AuthSecure> authSecures) { |
| | | this.authSecures.addAll(authSecures); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * è¿åèªå®ä¹ææéå |
| | | */ |
| | | public List<AuthSecure> getAuthSecures() { |
| | | return this.authSecures; |
| | | } |
| | | |
| | | /** |
| | | * 设置åºç¡è®¤è¯ |
| | | */ |
| | | public SecureRegistry addBasicPattern(HttpMethod method, String pattern, String username, String password) { |
| | | this.basicSecures.add(new BasicSecure(method, pattern, username, password)); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置åºç¡è®¤è¯éå |
| | | */ |
| | | public SecureRegistry addBasicPatterns(List<BasicSecure> basicSecures) { |
| | | this.basicSecures.addAll(basicSecures); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * è¿ååºç¡è®¤è¯éå |
| | | */ |
| | | public List<BasicSecure> getBasicSecures() { |
| | | return this.basicSecures; |
| | | } |
| | | |
| | | /** |
| | | * 设置ç¾åè®¤è¯ |
| | | */ |
| | | public SecureRegistry addSignPattern(HttpMethod method, String pattern, String crypto) { |
| | | this.signSecures.add(new SignSecure(method, pattern, crypto)); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置ç¾å认è¯éå |
| | | */ |
| | | public SecureRegistry addSignPatterns(List<SignSecure> signSecures) { |
| | | this.signSecures.addAll(signSecures); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * è¿åç¾å认è¯éå |
| | | */ |
| | | public List<SignSecure> getSignSecures() { |
| | | return this.signSecures; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.secure.utils; |
| | | |
| | | import io.jsonwebtoken.JwtBuilder; |
| | | import io.jsonwebtoken.Jwts; |
| | | import io.jsonwebtoken.SignatureAlgorithm; |
| | | import lombok.SneakyThrows; |
| | | import org.springblade.core.jwt.JwtUtil; |
| | | import org.springblade.core.jwt.props.JwtProperties; |
| | | import org.springblade.core.launch.constant.TokenConstant; |
| | | import org.springblade.core.secure.TokenInfo; |
| | | import org.springblade.core.secure.constant.SecureConstant; |
| | | import org.springblade.core.secure.exception.SecureException; |
| | | import org.springblade.core.secure.provider.IClientDetails; |
| | | import org.springblade.core.secure.provider.IClientDetailsService; |
| | | import org.springblade.core.tool.utils.*; |
| | | |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.security.Key; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * Secureå·¥å
·ç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class SecureUtil extends AuthUtil { |
| | | private final static String CLIENT_ID = TokenConstant.CLIENT_ID; |
| | | |
| | | private static IClientDetailsService clientDetailsService; |
| | | |
| | | private static JwtProperties jwtProperties; |
| | | |
| | | /** |
| | | * è·å客æ·ç«¯æå¡ç±» |
| | | * |
| | | * @return clientDetailsService |
| | | */ |
| | | private static IClientDetailsService getClientDetailsService() { |
| | | if (clientDetailsService == null) { |
| | | clientDetailsService = SpringUtil.getBean(IClientDetailsService.class); |
| | | } |
| | | return clientDetailsService; |
| | | } |
| | | |
| | | /** |
| | | * è·åé
置类 |
| | | * |
| | | * @return jwtProperties |
| | | */ |
| | | private static JwtProperties getJwtProperties() { |
| | | if (jwtProperties == null) { |
| | | jwtProperties = SpringUtil.getBean(JwtProperties.class); |
| | | } |
| | | return jwtProperties; |
| | | } |
| | | |
| | | /** |
| | | * å建令ç |
| | | * |
| | | * @param user user |
| | | * @param audience audience |
| | | * @param issuer issuer |
| | | * @param tokenType tokenType |
| | | * @return jwt |
| | | */ |
| | | public static TokenInfo createJWT(Map<String, Object> user, String audience, String issuer, String tokenType) { |
| | | |
| | | String[] tokens = extractAndDecodeHeader(); |
| | | String clientId = tokens[0]; |
| | | String clientSecret = tokens[1]; |
| | | |
| | | // è·å客æ·ç«¯ä¿¡æ¯ |
| | | IClientDetails clientDetails = clientDetails(clientId); |
| | | |
| | | // æ ¡éªå®¢æ·ç«¯ä¿¡æ¯ |
| | | if (!validateClient(clientDetails, clientId, clientSecret)) { |
| | | throw new SecureException("客æ·ç«¯è®¤è¯å¤±è´¥, è¯·æ£æ¥è¯·æ±å¤´ [Authorization] ä¿¡æ¯"); |
| | | } |
| | | |
| | | SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; |
| | | |
| | | long nowMillis = System.currentTimeMillis(); |
| | | Date now = new Date(nowMillis); |
| | | |
| | | //çæç¾åå¯é¥ |
| | | byte[] apiKeySecretBytes = Base64.getDecoder().decode(JwtUtil.getBase64Security()); |
| | | Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName()); |
| | | |
| | | //æ·»å ææJWTçç±» |
| | | JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT") |
| | | .setIssuer(issuer) |
| | | .setAudience(audience) |
| | | .signWith(signingKey); |
| | | |
| | | //设置JWTåæ° |
| | | user.forEach(builder::claim); |
| | | |
| | | //设置åºç¨id |
| | | builder.claim(CLIENT_ID, clientId); |
| | | |
| | | //æ·»å Tokenè¿ææ¶é´ |
| | | long expireMillis; |
| | | if (tokenType.equals(TokenConstant.ACCESS_TOKEN)) { |
| | | expireMillis = clientDetails.getAccessTokenValidity() * 1000L; |
| | | } else if (tokenType.equals(TokenConstant.REFRESH_TOKEN)) { |
| | | expireMillis = clientDetails.getRefreshTokenValidity() * 1000L; |
| | | } else { |
| | | expireMillis = getExpire(); |
| | | } |
| | | long expMillis = nowMillis + expireMillis; |
| | | Date exp = new Date(expMillis); |
| | | builder.setExpiration(exp).setNotBefore(now); |
| | | |
| | | //ç»è£
Tokenä¿¡æ¯ |
| | | TokenInfo tokenInfo = new TokenInfo(); |
| | | tokenInfo.setToken(builder.compact()); |
| | | tokenInfo.setExpire((int) (expireMillis / 1000L)); |
| | | |
| | | //Tokenç¶æé
ç½®, ä»
å¨çæAccessTokenæ¶åæ§è¡ |
| | | if (getJwtProperties().getState() && TokenConstant.ACCESS_TOKEN.equals(tokenType)) { |
| | | String tenantId = String.valueOf(user.get(TokenConstant.TENANT_ID)); |
| | | String userId = String.valueOf(user.get(TokenConstant.USER_ID)); |
| | | JwtUtil.addAccessToken(tenantId, userId, tokenInfo.getToken(), tokenInfo.getExpire()); |
| | | } |
| | | //Tokenç¶æé
ç½®, ä»
å¨çæRefreshTokenæ¶åæ§è¡ |
| | | if (getJwtProperties().getState() && getJwtProperties().getSingle() && TokenConstant.REFRESH_TOKEN.equals(tokenType)) { |
| | | String tenantId = String.valueOf(user.get(TokenConstant.TENANT_ID)); |
| | | String userId = String.valueOf(user.get(TokenConstant.USER_ID)); |
| | | JwtUtil.addRefreshToken(tenantId, userId, tokenInfo.getToken(), tokenInfo.getExpire()); |
| | | } |
| | | return tokenInfo; |
| | | } |
| | | |
| | | /** |
| | | * è·åè¿ææ¶é´(次æ¥åæ¨3ç¹) |
| | | * |
| | | * @return expire |
| | | */ |
| | | public static long getExpire() { |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.add(Calendar.DAY_OF_YEAR, 1); |
| | | cal.set(Calendar.HOUR_OF_DAY, 3); |
| | | cal.set(Calendar.SECOND, 0); |
| | | cal.set(Calendar.MINUTE, 0); |
| | | cal.set(Calendar.MILLISECOND, 0); |
| | | return cal.getTimeInMillis() - System.currentTimeMillis(); |
| | | } |
| | | |
| | | /** |
| | | * 客æ·ç«¯ä¿¡æ¯è§£ç |
| | | */ |
| | | @SneakyThrows |
| | | public static String[] extractAndDecodeHeader() { |
| | | // è·å请æ±å¤´å®¢æ·ç«¯ä¿¡æ¯ |
| | | String header = Objects.requireNonNull(WebUtil.getRequest()).getHeader(SecureConstant.BASIC_HEADER_KEY); |
| | | header = Func.toStr(header).replace(SecureConstant.BASIC_HEADER_PREFIX_EXT, SecureConstant.BASIC_HEADER_PREFIX); |
| | | if (!header.startsWith(SecureConstant.BASIC_HEADER_PREFIX)) { |
| | | throw new SecureException("æªè·åå°è¯·æ±å¤´[Authorization]çä¿¡æ¯"); |
| | | } |
| | | byte[] base64Token = header.substring(6).getBytes(Charsets.UTF_8_NAME); |
| | | |
| | | byte[] decoded; |
| | | try { |
| | | decoded = Base64.getDecoder().decode(base64Token); |
| | | } catch (IllegalArgumentException var7) { |
| | | throw new RuntimeException("客æ·ç«¯ä»¤çè§£æå¤±è´¥"); |
| | | } |
| | | |
| | | String token = new String(decoded, Charsets.UTF_8_NAME); |
| | | int index = token.indexOf(StringPool.COLON); |
| | | if (index == -1) { |
| | | throw new RuntimeException("客æ·ç«¯ä»¤çä¸åæ³"); |
| | | } else { |
| | | return new String[]{token.substring(0, index), token.substring(index + 1)}; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·å请æ±å¤´ä¸ç客æ·ç«¯id |
| | | */ |
| | | public static String getClientIdFromHeader() { |
| | | String[] tokens = extractAndDecodeHeader(); |
| | | assert tokens.length == 2; |
| | | return tokens[0]; |
| | | } |
| | | |
| | | /** |
| | | * è·å客æ·ç«¯ä¿¡æ¯ |
| | | * |
| | | * @param clientId 客æ·ç«¯id |
| | | * @return clientDetails |
| | | */ |
| | | private static IClientDetails clientDetails(String clientId) { |
| | | return getClientDetailsService().loadClientByClientId(clientId); |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªClient |
| | | * |
| | | * @param clientId 客æ·ç«¯id |
| | | * @param clientSecret 客æ·ç«¯å¯é¥ |
| | | * @return boolean |
| | | */ |
| | | private static boolean validateClient(IClientDetails clientDetails, String clientId, String clientSecret) { |
| | | if (clientDetails != null) { |
| | | return StringUtil.equals(clientId, clientDetails.getClientId()) && StringUtil.equals(clientSecret, clientDetails.getClientSecret()); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <groupId>org.springblade</groupId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-test</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <dependencies> |
| | | <!-- Blade --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-launch</artifactId> |
| | | </dependency> |
| | | <!-- Test --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-test</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.test; |
| | | |
| | | import org.junit.jupiter.api.extension.ExtendWith; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | import org.springframework.core.annotation.AliasFor; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * ç®å æµè¯ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Target({ElementType.METHOD, ElementType.TYPE}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | @Inherited |
| | | @SpringBootTest |
| | | @ExtendWith(BladeSpringExtension.class) |
| | | public @interface BladeBootTest { |
| | | /** |
| | | * æå¡åï¼appName |
| | | * @return appName |
| | | */ |
| | | @AliasFor("appName") |
| | | String value() default "blade-test"; |
| | | /** |
| | | * æå¡åï¼appName |
| | | * @return appName |
| | | */ |
| | | @AliasFor("value") |
| | | String appName() default "blade-test"; |
| | | /** |
| | | * profile |
| | | * @return profile |
| | | */ |
| | | String profile() default "dev"; |
| | | /** |
| | | * å¯ç¨ ServiceLoader å è½½ launcherService |
| | | * @return æ¯å¦å¯ç¨ |
| | | */ |
| | | boolean enableLoader() default false; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.test; |
| | | |
| | | /** |
| | | * blade test å¼å¸¸ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | class BladeBootTestException extends RuntimeException { |
| | | |
| | | BladeBootTestException(String message) { |
| | | super(message); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.test; |
| | | |
| | | |
| | | import org.junit.jupiter.api.extension.ExtensionContext; |
| | | import org.springblade.core.launch.BladeApplication; |
| | | import org.springblade.core.launch.constant.AppConstant; |
| | | import org.springblade.core.launch.constant.NacosConstant; |
| | | import org.springblade.core.launch.constant.SentinelConstant; |
| | | import org.springblade.core.launch.service.LauncherService; |
| | | import org.springframework.boot.builder.SpringApplicationBuilder; |
| | | import org.springframework.core.annotation.AnnotationUtils; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.test.context.junit.jupiter.SpringExtension; |
| | | |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 设置å¯å¨åæ° |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeSpringExtension extends SpringExtension { |
| | | |
| | | @Override |
| | | public void beforeAll(@NonNull ExtensionContext context) throws Exception { |
| | | super.beforeAll(context); |
| | | setUpTestClass(context); |
| | | } |
| | | |
| | | private void setUpTestClass(ExtensionContext context) { |
| | | Class<?> clazz = context.getRequiredTestClass(); |
| | | BladeBootTest bladeBootTest = AnnotationUtils.getAnnotation(clazz, BladeBootTest.class); |
| | | if (bladeBootTest == null) { |
| | | throw new BladeBootTestException(String.format("%s must be @BladeBootTest .", clazz)); |
| | | } |
| | | String appName = bladeBootTest.appName(); |
| | | String profile = bladeBootTest.profile(); |
| | | boolean isLocalDev = BladeApplication.isLocalDev(); |
| | | Properties props = System.getProperties(); |
| | | props.setProperty("blade.env", profile); |
| | | props.setProperty("blade.name", appName); |
| | | props.setProperty("blade.is-local", String.valueOf(isLocalDev)); |
| | | props.setProperty("blade.dev-mode", profile.equals(AppConstant.PROD_CODE) ? "false" : "true"); |
| | | props.setProperty("blade.service.version", AppConstant.APPLICATION_VERSION); |
| | | props.setProperty("spring.application.name", appName); |
| | | props.setProperty("spring.profiles.active", profile); |
| | | props.setProperty("info.version", AppConstant.APPLICATION_VERSION); |
| | | props.setProperty("info.desc", appName); |
| | | props.setProperty("loadbalancer.client.name", appName); |
| | | props.setProperty("spring.cloud.sentinel.transport.dashboard", SentinelConstant.SENTINEL_ADDR); |
| | | props.setProperty("spring.main.allow-bean-definition-overriding", "true"); |
| | | props.setProperty("spring.cloud.nacos.config.shared-configs[0].data-id", NacosConstant.sharedDataId()); |
| | | props.setProperty("spring.cloud.nacos.config.shared-configs[0].group", NacosConstant.NACOS_CONFIG_GROUP); |
| | | props.setProperty("spring.cloud.nacos.config.shared-configs[0].refresh", NacosConstant.NACOS_CONFIG_REFRESH); |
| | | props.setProperty("spring.cloud.nacos.config.file-extension", NacosConstant.NACOS_CONFIG_FORMAT); |
| | | props.setProperty("spring.cloud.nacos.config.shared-configs[1].data-id", NacosConstant.sharedDataId(profile)); |
| | | props.setProperty("spring.cloud.nacos.config.shared-configs[1].group", NacosConstant.NACOS_CONFIG_GROUP); |
| | | props.setProperty("spring.cloud.nacos.config.shared-configs[1].refresh", NacosConstant.NACOS_CONFIG_REFRESH); |
| | | // å è½½èªå®ä¹ç»ä»¶ |
| | | if (bladeBootTest.enableLoader()) { |
| | | SpringApplicationBuilder builder = new SpringApplicationBuilder(clazz); |
| | | List<LauncherService> launcherList = new ArrayList<>(); |
| | | ServiceLoader.load(LauncherService.class).forEach(launcherList::add); |
| | | launcherList.stream().sorted(Comparator.comparing(LauncherService::getOrder)).collect(Collectors.toList()) |
| | | .forEach(launcherService -> launcherService.launcher(builder, appName, profile, isLocalDev)); |
| | | } |
| | | System.err.printf("---[junit.test]:[%s]---å¯å¨ä¸ï¼è¯»åå°çç¯å¢åé:[%s]%n", appName, profile); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0"?> |
| | | <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"> |
| | | |
| | | <parent> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>BladeX-Tool</artifactId> |
| | | <version>3.0.1.RELEASE</version> |
| | | </parent> |
| | | |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>blade-core-tool</artifactId> |
| | | <name>${project.artifactId}</name> |
| | | <version>${project.parent.version}</version> |
| | | <packaging>jar</packaging> |
| | | |
| | | <dependencies> |
| | | <!-- Blade --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-launch</artifactId> |
| | | </dependency> |
| | | <!-- Jackson --> |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.datatype</groupId> |
| | | <artifactId>jackson-datatype-jsr310</artifactId> |
| | | </dependency> |
| | | <!-- Guava --> |
| | | <dependency> |
| | | <groupId>com.google.guava</groupId> |
| | | <artifactId>guava</artifactId> |
| | | </dependency> |
| | | <!--Swagger--> |
| | | <dependency> |
| | | <groupId>io.springfox</groupId> |
| | | <artifactId>springfox-swagger2</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>io.swagger</groupId> |
| | | <artifactId>swagger-models</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.swagger</groupId> |
| | | <artifactId>swagger-models</artifactId> |
| | | </dependency> |
| | | <!-- protostuff --> |
| | | <dependency> |
| | | <groupId>io.protostuff</groupId> |
| | | <artifactId>protostuff-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.protostuff</groupId> |
| | | <artifactId>protostuff-runtime</artifactId> |
| | | </dependency> |
| | | <!-- jackson --> |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.module</groupId> |
| | | <artifactId>jackson-module-jaxb-annotations</artifactId> |
| | | </dependency> |
| | | <!-- validation --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-validation</artifactId> |
| | | </dependency> |
| | | <!-- Auto --> |
| | | <dependency> |
| | | <groupId>org.springblade</groupId> |
| | | <artifactId>blade-core-auto</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.api; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * ä¸å¡ä»£ç æ¥å£ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface IResultCode extends Serializable { |
| | | |
| | | /** |
| | | * è·åæ¶æ¯ |
| | | * |
| | | * @return |
| | | */ |
| | | String getMessage(); |
| | | |
| | | /** |
| | | * è·åç¶æç |
| | | * |
| | | * @return |
| | | */ |
| | | int getCode(); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.api; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.*; |
| | | import org.springblade.core.tool.constant.BladeConstant; |
| | | import org.springblade.core.tool.utils.ObjectUtil; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.Serializable; |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | | * ç»ä¸APIååºç»æå°è£
|
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @ToString |
| | | @ApiModel(description = "è¿åä¿¡æ¯") |
| | | @NoArgsConstructor |
| | | public class R<T> implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty(value = "ç¶æç ", required = true) |
| | | private int code; |
| | | @ApiModelProperty(value = "æ¯å¦æå", required = true) |
| | | private boolean success; |
| | | @ApiModelProperty(value = "æ¿è½½æ°æ®") |
| | | private T data; |
| | | @ApiModelProperty(value = "è¿åæ¶æ¯", required = true) |
| | | private String msg; |
| | | |
| | | private R(IResultCode resultCode) { |
| | | this(resultCode, null, resultCode.getMessage()); |
| | | } |
| | | |
| | | private R(IResultCode resultCode, String msg) { |
| | | this(resultCode, null, msg); |
| | | } |
| | | |
| | | private R(IResultCode resultCode, T data) { |
| | | this(resultCode, data, resultCode.getMessage()); |
| | | } |
| | | |
| | | private R(IResultCode resultCode, T data, String msg) { |
| | | this(resultCode.getCode(), data, msg); |
| | | } |
| | | |
| | | private R(int code, T data, String msg) { |
| | | this.code = code; |
| | | this.data = data; |
| | | this.msg = msg; |
| | | this.success = ResultCode.SUCCESS.code == code; |
| | | } |
| | | |
| | | /** |
| | | * 夿è¿åæ¯å¦ä¸ºæå |
| | | * |
| | | * @param result Result |
| | | * @return æ¯å¦æå |
| | | */ |
| | | public static boolean isSuccess(@Nullable R<?> result) { |
| | | return Optional.ofNullable(result) |
| | | .map(x -> ObjectUtil.nullSafeEquals(ResultCode.SUCCESS.code, x.code)) |
| | | .orElse(Boolean.FALSE); |
| | | } |
| | | |
| | | /** |
| | | * 夿è¿åæ¯å¦ä¸ºæå |
| | | * |
| | | * @param result Result |
| | | * @return æ¯å¦æå |
| | | */ |
| | | public static boolean isNotSuccess(@Nullable R<?> result) { |
| | | return !R.isSuccess(result); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param data æ°æ® |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> data(T data) { |
| | | return data(data, BladeConstant.DEFAULT_SUCCESS_MESSAGE); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param data æ°æ® |
| | | * @param msg æ¶æ¯ |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> data(T data, String msg) { |
| | | return data(HttpServletResponse.SC_OK, data, msg); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param code ç¶æç |
| | | * @param data æ°æ® |
| | | * @param msg æ¶æ¯ |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> data(int code, T data, String msg) { |
| | | return new R<>(code, data, data == null ? BladeConstant.DEFAULT_NULL_MESSAGE : msg); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param msg æ¶æ¯ |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> success(String msg) { |
| | | return new R<>(ResultCode.SUCCESS, msg); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param resultCode ä¸å¡ä»£ç |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> success(IResultCode resultCode) { |
| | | return new R<>(resultCode); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param resultCode ä¸å¡ä»£ç |
| | | * @param msg æ¶æ¯ |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> success(IResultCode resultCode, String msg) { |
| | | return new R<>(resultCode, msg); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param msg æ¶æ¯ |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> fail(String msg) { |
| | | return new R<>(ResultCode.FAILURE, msg); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param code ç¶æç |
| | | * @param msg æ¶æ¯ |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> fail(int code, String msg) { |
| | | return new R<>(code, null, msg); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param resultCode ä¸å¡ä»£ç |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> fail(IResultCode resultCode) { |
| | | return new R<>(resultCode); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param resultCode ä¸å¡ä»£ç |
| | | * @param msg æ¶æ¯ |
| | | * @param <T> T æ³åæ è®° |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> fail(IResultCode resultCode, String msg) { |
| | | return new R<>(resultCode, msg); |
| | | } |
| | | |
| | | /** |
| | | * è¿åR |
| | | * |
| | | * @param flag æåç¶æ |
| | | * @return R |
| | | */ |
| | | public static <T> R<T> status(boolean flag) { |
| | | return flag ? success(BladeConstant.DEFAULT_SUCCESS_MESSAGE) : fail(BladeConstant.DEFAULT_FAILURE_MESSAGE); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.api; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | /** |
| | | * ä¸å¡ä»£ç æä¸¾ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum ResultCode implements IResultCode { |
| | | |
| | | /** |
| | | * æä½æå |
| | | */ |
| | | SUCCESS(HttpServletResponse.SC_OK, "æä½æå"), |
| | | |
| | | /** |
| | | * ä¸å¡å¼å¸¸ |
| | | */ |
| | | FAILURE(HttpServletResponse.SC_BAD_REQUEST, "ä¸å¡å¼å¸¸"), |
| | | |
| | | /** |
| | | * è¯·æ±æªææ |
| | | */ |
| | | UN_AUTHORIZED(HttpServletResponse.SC_UNAUTHORIZED, "è¯·æ±æªææ"), |
| | | |
| | | /** |
| | | * 客æ·ç«¯è¯·æ±æªææ |
| | | */ |
| | | CLIENT_UN_AUTHORIZED(HttpServletResponse.SC_UNAUTHORIZED, "客æ·ç«¯è¯·æ±æªææ"), |
| | | |
| | | /** |
| | | * 404 没æ¾å°è¯·æ± |
| | | */ |
| | | NOT_FOUND(HttpServletResponse.SC_NOT_FOUND, "404 没æ¾å°è¯·æ±"), |
| | | |
| | | /** |
| | | * æ¶æ¯ä¸è½è¯»å |
| | | */ |
| | | MSG_NOT_READABLE(HttpServletResponse.SC_BAD_REQUEST, "æ¶æ¯ä¸è½è¯»å"), |
| | | |
| | | /** |
| | | * 䏿¯æå½åè¯·æ±æ¹æ³ |
| | | */ |
| | | METHOD_NOT_SUPPORTED(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "䏿¯æå½åè¯·æ±æ¹æ³"), |
| | | |
| | | /** |
| | | * 䏿¯æå½ååªä½ç±»å |
| | | */ |
| | | MEDIA_TYPE_NOT_SUPPORTED(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, "䏿¯æå½ååªä½ç±»å"), |
| | | |
| | | /** |
| | | * 请æ±è¢«æç» |
| | | */ |
| | | REQ_REJECT(HttpServletResponse.SC_FORBIDDEN, "请æ±è¢«æç»"), |
| | | |
| | | /** |
| | | * æå¡å¨å¼å¸¸ |
| | | */ |
| | | INTERNAL_SERVER_ERROR(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "æå¡å¨å¼å¸¸"), |
| | | |
| | | /** |
| | | * 缺å°å¿
è¦ç请æ±åæ° |
| | | */ |
| | | PARAM_MISS(HttpServletResponse.SC_BAD_REQUEST, "缺å°å¿
è¦ç请æ±åæ°"), |
| | | |
| | | /** |
| | | * 请æ±åæ°ç±»åé误 |
| | | */ |
| | | PARAM_TYPE_ERROR(HttpServletResponse.SC_BAD_REQUEST, "请æ±åæ°ç±»åé误"), |
| | | |
| | | /** |
| | | * 请æ±åæ°ç»å®é误 |
| | | */ |
| | | PARAM_BIND_ERROR(HttpServletResponse.SC_BAD_REQUEST, "请æ±åæ°ç»å®é误"), |
| | | |
| | | /** |
| | | * åæ°æ ¡éªå¤±è´¥ |
| | | */ |
| | | PARAM_VALID_ERROR(HttpServletResponse.SC_BAD_REQUEST, "åæ°æ ¡éªå¤±è´¥"), |
| | | ; |
| | | |
| | | /** |
| | | * codeç¼ç |
| | | */ |
| | | final int code; |
| | | /** |
| | | * ä¸æä¿¡æ¯æè¿° |
| | | */ |
| | | final String message; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.beans; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * Bean屿§ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public class BeanProperty { |
| | | private final String name; |
| | | private final Class<?> type; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.beans; |
| | | |
| | | |
| | | import org.springblade.core.tool.utils.BeanUtil; |
| | | import org.springblade.core.tool.utils.ClassUtil; |
| | | import org.springblade.core.tool.utils.ReflectUtil; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springframework.asm.ClassVisitor; |
| | | import org.springframework.asm.Label; |
| | | import org.springframework.asm.Opcodes; |
| | | import org.springframework.asm.Type; |
| | | import org.springframework.cglib.core.*; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.util.ClassUtils; |
| | | |
| | | import java.beans.PropertyDescriptor; |
| | | import java.lang.reflect.Method; |
| | | import java.lang.reflect.Modifier; |
| | | import java.security.ProtectionDomain; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ConcurrentMap; |
| | | |
| | | /** |
| | | * spring cglib éæ¹ |
| | | * |
| | | * <p> |
| | | * 1. æ¯æé¾å¼ beanï¼æ¯æ map |
| | | * 2. ClassLoader è· target ä¿æä¸è´ |
| | | * </p> |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public abstract class BladeBeanCopier { |
| | | private static final Type CONVERTER = TypeUtils.parseType("org.springframework.cglib.core.Converter"); |
| | | private static final Type BEAN_COPIER = TypeUtils.parseType(BladeBeanCopier.class.getName()); |
| | | private static final Type BEAN_MAP = TypeUtils.parseType(Map.class.getName()); |
| | | private static final Signature COPY = new Signature("copy", Type.VOID_TYPE, new Type[]{Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER}); |
| | | private static final Signature CONVERT = TypeUtils.parseSignature("Object convert(Object, Class, Object)"); |
| | | private static final Signature BEAN_MAP_GET = TypeUtils.parseSignature("Object get(Object)"); |
| | | private static final Type CLASS_UTILS = TypeUtils.parseType(ClassUtils.class.getName()); |
| | | private static final Signature IS_ASSIGNABLE_VALUE = TypeUtils.parseSignature("boolean isAssignableValue(Class, Object)"); |
| | | /** |
| | | * The map to store {@link BladeBeanCopier} of source type and class type for copy. |
| | | */ |
| | | private static final ConcurrentMap<BladeBeanCopierKey, BladeBeanCopier> BEAN_COPIER_MAP = new ConcurrentHashMap<>(); |
| | | |
| | | public static BladeBeanCopier create(Class source, Class target, boolean useConverter) { |
| | | return BladeBeanCopier.create(source, target, useConverter, false); |
| | | } |
| | | |
| | | public static BladeBeanCopier create(Class source, Class target, boolean useConverter, boolean nonNull) { |
| | | BladeBeanCopierKey copierKey = new BladeBeanCopierKey(source, target, useConverter, nonNull); |
| | | // å©ç¨ ConcurrentMap ç¼å æé«æ§è½ï¼æ¥è¿ ç´æ¥ get set |
| | | return BEAN_COPIER_MAP.computeIfAbsent(copierKey, key -> { |
| | | Generator gen = new Generator(); |
| | | gen.setSource(key.getSource()); |
| | | gen.setTarget(key.getTarget()); |
| | | gen.setUseConverter(key.isUseConverter()); |
| | | gen.setNonNull(key.isNonNull()); |
| | | return gen.create(key); |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * Bean copy |
| | | * |
| | | * @param from from Bean |
| | | * @param to to Bean |
| | | * @param converter Converter |
| | | */ |
| | | abstract public void copy(Object from, Object to, @Nullable Converter converter); |
| | | |
| | | public static class Generator extends AbstractClassGenerator { |
| | | private static final Source SOURCE = new Source(BladeBeanCopier.class.getName()); |
| | | private Class source; |
| | | private Class target; |
| | | private boolean useConverter; |
| | | private boolean nonNull; |
| | | |
| | | Generator() { |
| | | super(SOURCE); |
| | | } |
| | | |
| | | public void setSource(Class source) { |
| | | if (!Modifier.isPublic(source.getModifiers())) { |
| | | setNamePrefix(source.getName()); |
| | | } |
| | | this.source = source; |
| | | } |
| | | |
| | | public void setTarget(Class target) { |
| | | if (!Modifier.isPublic(target.getModifiers())) { |
| | | setNamePrefix(target.getName()); |
| | | } |
| | | this.target = target; |
| | | } |
| | | |
| | | public void setUseConverter(boolean useConverter) { |
| | | this.useConverter = useConverter; |
| | | } |
| | | |
| | | public void setNonNull(boolean nonNull) { |
| | | this.nonNull = nonNull; |
| | | } |
| | | |
| | | @Override |
| | | protected ClassLoader getDefaultClassLoader() { |
| | | // L.cm ä¿è¯ å è¿å使ç¨åä¸ä¸ª ClassLoader |
| | | return target.getClassLoader(); |
| | | } |
| | | |
| | | @Override |
| | | protected ProtectionDomain getProtectionDomain() { |
| | | return ReflectUtils.getProtectionDomain(source); |
| | | } |
| | | |
| | | @Override |
| | | public BladeBeanCopier create(Object key) { |
| | | return (BladeBeanCopier) super.create(key); |
| | | } |
| | | |
| | | @Override |
| | | public void generateClass(ClassVisitor v) { |
| | | Type sourceType = Type.getType(source); |
| | | Type targetType = Type.getType(target); |
| | | ClassEmitter ce = new ClassEmitter(v); |
| | | ce.begin_class(Constants.V1_2, |
| | | Constants.ACC_PUBLIC, |
| | | getClassName(), |
| | | BEAN_COPIER, |
| | | null, |
| | | Constants.SOURCE_FILE); |
| | | |
| | | EmitUtils.null_constructor(ce); |
| | | CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null); |
| | | |
| | | // map åç¬å¤ç |
| | | if (Map.class.isAssignableFrom(source)) { |
| | | generateClassFormMap(ce, e, sourceType, targetType); |
| | | return; |
| | | } |
| | | |
| | | // 2018.12.27 by L.cm æ¯æé¾å¼ bean |
| | | // 注æï¼æ¤å¤éå
¼å®¹é¾å¼bean 使ç¨äº spring çæ¹æ³ï¼æ¯è¾èæ¶ |
| | | PropertyDescriptor[] getters = ReflectUtil.getBeanGetters(source); |
| | | PropertyDescriptor[] setters = ReflectUtil.getBeanSetters(target); |
| | | Map<String, PropertyDescriptor> names = new HashMap<>(16); |
| | | for (PropertyDescriptor getter : getters) { |
| | | names.put(getter.getName(), getter); |
| | | } |
| | | |
| | | Local targetLocal = e.make_local(); |
| | | Local sourceLocal = e.make_local(); |
| | | e.load_arg(1); |
| | | e.checkcast(targetType); |
| | | e.store_local(targetLocal); |
| | | e.load_arg(0); |
| | | e.checkcast(sourceType); |
| | | e.store_local(sourceLocal); |
| | | |
| | | for (PropertyDescriptor setter : setters) { |
| | | String propName = setter.getName(); |
| | | |
| | | CopyProperty targetIgnoreCopy = ReflectUtil.getAnnotation(target, propName, CopyProperty.class); |
| | | // set ä¸æå¿½ç¥ç 注解 |
| | | if (targetIgnoreCopy != null) { |
| | | if (targetIgnoreCopy.ignore()) { |
| | | continue; |
| | | } |
| | | // 注解ä¸çå«åï¼å¦æå«åä¸ä¸ºç©ºï¼ä½¿ç¨å«å |
| | | String aliasTargetPropName = targetIgnoreCopy.value(); |
| | | if (StringUtil.isNotBlank(aliasTargetPropName)) { |
| | | propName = aliasTargetPropName; |
| | | } |
| | | } |
| | | // æ¾å°å¯¹åºç get |
| | | PropertyDescriptor getter = names.get(propName); |
| | | // 没æ get è·³åº |
| | | if (getter == null) { |
| | | continue; |
| | | } |
| | | |
| | | MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod()); |
| | | Method writeMethod = setter.getWriteMethod(); |
| | | MethodInfo write = ReflectUtils.getMethodInfo(writeMethod); |
| | | Type returnType = read.getSignature().getReturnType(); |
| | | Type setterType = write.getSignature().getArgumentTypes()[0]; |
| | | Class<?> getterPropertyType = getter.getPropertyType(); |
| | | Class<?> setterPropertyType = setter.getPropertyType(); |
| | | |
| | | // L.cm 2019.01.12 ä¼åé»è¾ï¼å
å¤æç±»åï¼ç±»åä¸è´ç´æ¥ setï¼ä¸åå夿 æ¯å¦ ç±»åè½¬æ¢ |
| | | // nonNull Label |
| | | Label l0 = e.make_label(); |
| | | // å¤æç±»åæ¯å¦ä¸è´ï¼å
æ¬ å
è£
ç±»å |
| | | if (ClassUtil.isAssignable(setterPropertyType, getterPropertyType)) { |
| | | // 2018.12.27 by L.cm æ¯æé¾å¼ bean |
| | | e.load_local(targetLocal); |
| | | e.load_local(sourceLocal); |
| | | e.invoke(read); |
| | | boolean getterIsPrimitive = getterPropertyType.isPrimitive(); |
| | | boolean setterIsPrimitive = setterPropertyType.isPrimitive(); |
| | | |
| | | if (nonNull) { |
| | | // éè¦è½æ ï¼å¼ºå¶è£
ç®± |
| | | e.box(returnType); |
| | | Local var = e.make_local(); |
| | | e.store_local(var); |
| | | e.load_local(var); |
| | | // nonNull Label |
| | | e.ifnull(l0); |
| | | e.load_local(targetLocal); |
| | | e.load_local(var); |
| | | // éè¦è½æ ï¼å¼ºå¶æç®± |
| | | e.unbox_or_zero(setterType); |
| | | } else { |
| | | // 妿 get 为åå§ç±»åï¼éè¦è£
ç®± |
| | | if (getterIsPrimitive && !setterIsPrimitive) { |
| | | e.box(returnType); |
| | | } |
| | | // 妿 set 为åå§ç±»åï¼éè¦æç®± |
| | | if (!getterIsPrimitive && setterIsPrimitive) { |
| | | e.unbox_or_zero(setterType); |
| | | } |
| | | } |
| | | |
| | | // æé set æ¹æ³ |
| | | invokeWrite(e, write, writeMethod, nonNull, l0); |
| | | } else if (useConverter) { |
| | | e.load_local(targetLocal); |
| | | e.load_arg(2); |
| | | e.load_local(sourceLocal); |
| | | e.invoke(read); |
| | | e.box(returnType); |
| | | |
| | | if (nonNull) { |
| | | Local var = e.make_local(); |
| | | e.store_local(var); |
| | | e.load_local(var); |
| | | e.ifnull(l0); |
| | | e.load_local(targetLocal); |
| | | e.load_arg(2); |
| | | e.load_local(var); |
| | | } |
| | | |
| | | EmitUtils.load_class(e, setterType); |
| | | // æ´æ¹æäºå±æ§åï¼ä¹åæ¯ set æ¹æ³å |
| | | e.push(propName); |
| | | e.invoke_interface(CONVERTER, CONVERT); |
| | | e.unbox_or_zero(setterType); |
| | | |
| | | // æé set æ¹æ³ |
| | | invokeWrite(e, write, writeMethod, nonNull, l0); |
| | | } |
| | | } |
| | | e.return_value(); |
| | | e.end_method(); |
| | | ce.end_class(); |
| | | } |
| | | |
| | | private static void invokeWrite(CodeEmitter e, MethodInfo write, Method writeMethod, boolean nonNull, Label l0) { |
| | | // è¿åå¼ï¼å¤æ é¾å¼ bean |
| | | Class<?> returnType = writeMethod.getReturnType(); |
| | | e.invoke(write); |
| | | // é¾å¼ beanï¼æè¿åå¼éè¦ pop |
| | | if (!returnType.equals(Void.TYPE)) { |
| | | e.pop(); |
| | | } |
| | | if (nonNull) { |
| | | e.visitLabel(l0); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected Object firstInstance(Class type) { |
| | | return BeanUtil.newInstance(type); |
| | | } |
| | | |
| | | @Override |
| | | protected Object nextInstance(Object instance) { |
| | | return instance; |
| | | } |
| | | |
| | | /** |
| | | * å¤ç map ç copy |
| | | * @param ce ClassEmitter |
| | | * @param e CodeEmitter |
| | | * @param sourceType sourceType |
| | | * @param targetType targetType |
| | | */ |
| | | public void generateClassFormMap(ClassEmitter ce, CodeEmitter e, Type sourceType, Type targetType) { |
| | | // 2018.12.27 by L.cm æ¯æé¾å¼ bean |
| | | PropertyDescriptor[] setters = ReflectUtil.getBeanSetters(target); |
| | | |
| | | // å
¥å£åé |
| | | Local targetLocal = e.make_local(); |
| | | Local sourceLocal = e.make_local(); |
| | | e.load_arg(1); |
| | | e.checkcast(targetType); |
| | | e.store_local(targetLocal); |
| | | e.load_arg(0); |
| | | e.checkcast(sourceType); |
| | | e.store_local(sourceLocal); |
| | | Type mapBox = Type.getType(Object.class); |
| | | |
| | | for (PropertyDescriptor setter : setters) { |
| | | String propName = setter.getName(); |
| | | |
| | | // set ä¸æå¿½ç¥ç 注解 |
| | | CopyProperty targetIgnoreCopy = ReflectUtil.getAnnotation(target, propName, CopyProperty.class); |
| | | if (targetIgnoreCopy != null) { |
| | | if (targetIgnoreCopy.ignore()) { |
| | | continue; |
| | | } |
| | | // 注解ä¸çå«å |
| | | String aliasTargetPropName = targetIgnoreCopy.value(); |
| | | if (StringUtil.isNotBlank(aliasTargetPropName)) { |
| | | propName = aliasTargetPropName; |
| | | } |
| | | } |
| | | |
| | | Method writeMethod = setter.getWriteMethod(); |
| | | MethodInfo write = ReflectUtils.getMethodInfo(writeMethod); |
| | | Type setterType = write.getSignature().getArgumentTypes()[0]; |
| | | |
| | | e.load_local(targetLocal); |
| | | e.load_local(sourceLocal); |
| | | |
| | | e.push(propName); |
| | | // æ§è¡ map get |
| | | e.invoke_interface(BEAN_MAP, BEAN_MAP_GET); |
| | | // box è£
ç®±ï¼é¿å
array[] æ°ç»é®é¢ |
| | | e.box(mapBox); |
| | | |
| | | // çæåé |
| | | Local var = e.make_local(); |
| | | e.store_local(var); |
| | | e.load_local(var); |
| | | |
| | | // å
夿 ä¸ä¸ºnullï¼ç¶ååç±»å夿 |
| | | Label l0 = e.make_label(); |
| | | e.ifnull(l0); |
| | | EmitUtils.load_class(e, setterType); |
| | | e.load_local(var); |
| | | // ClassUtils.isAssignableValue(Integer.class, id) |
| | | e.invoke_static(CLASS_UTILS, IS_ASSIGNABLE_VALUE); |
| | | Label l1 = new Label(); |
| | | // è¿åå¼ï¼å¤æ é¾å¼ bean |
| | | Class<?> returnType = writeMethod.getReturnType(); |
| | | if (useConverter) { |
| | | e.if_jump(Opcodes.IFEQ, l1); |
| | | e.load_local(targetLocal); |
| | | e.load_local(var); |
| | | e.unbox_or_zero(setterType); |
| | | e.invoke(write); |
| | | if (!returnType.equals(Void.TYPE)) { |
| | | e.pop(); |
| | | } |
| | | e.goTo(l0); |
| | | e.visitLabel(l1); |
| | | e.load_local(targetLocal); |
| | | e.load_arg(2); |
| | | e.load_local(var); |
| | | EmitUtils.load_class(e, setterType); |
| | | e.push(propName); |
| | | e.invoke_interface(CONVERTER, CONVERT); |
| | | e.unbox_or_zero(setterType); |
| | | e.invoke(write); |
| | | } else { |
| | | e.if_jump(Opcodes.IFEQ, l0); |
| | | e.load_local(targetLocal); |
| | | e.load_local(var); |
| | | e.unbox_or_zero(setterType); |
| | | e.invoke(write); |
| | | } |
| | | // è¿åå¼ï¼å¤æ é¾å¼ bean |
| | | if (!returnType.equals(Void.TYPE)) { |
| | | e.pop(); |
| | | } |
| | | e.visitLabel(l0); |
| | | } |
| | | e.return_value(); |
| | | e.end_method(); |
| | | ce.end_class(); |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.beans; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * copy key |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | @EqualsAndHashCode |
| | | @AllArgsConstructor |
| | | public class BladeBeanCopierKey { |
| | | private final Class<?> source; |
| | | private final Class<?> target; |
| | | private final boolean useConverter; |
| | | private final boolean nonNull; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.beans; |
| | | |
| | | import org.springframework.asm.ClassVisitor; |
| | | import org.springframework.cglib.beans.BeanMap; |
| | | import org.springframework.cglib.core.AbstractClassGenerator; |
| | | import org.springframework.cglib.core.ReflectUtils; |
| | | |
| | | import java.security.ProtectionDomain; |
| | | |
| | | /** |
| | | * éå cglib BeanMapï¼æ¯æé¾å¼bean |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public abstract class BladeBeanMap extends BeanMap { |
| | | protected BladeBeanMap() { |
| | | } |
| | | |
| | | protected BladeBeanMap(Object bean) { |
| | | super(bean); |
| | | } |
| | | |
| | | public static BladeBeanMap create(Object bean) { |
| | | BladeGenerator gen = new BladeGenerator(); |
| | | gen.setBean(bean); |
| | | return gen.create(); |
| | | } |
| | | |
| | | /** |
| | | * newInstance |
| | | * |
| | | * @param o Object |
| | | * @return BladeBeanMap |
| | | */ |
| | | @Override |
| | | public abstract BladeBeanMap newInstance(Object o); |
| | | |
| | | public static class BladeGenerator extends AbstractClassGenerator { |
| | | private static final Source SOURCE = new Source(BladeBeanMap.class.getName()); |
| | | |
| | | private Object bean; |
| | | private Class beanClass; |
| | | private int require; |
| | | |
| | | public BladeGenerator() { |
| | | super(SOURCE); |
| | | } |
| | | |
| | | /** |
| | | * Set the bean that the generated map should reflect. The bean may be swapped |
| | | * out for another bean of the same type using {@link #setBean}. |
| | | * Calling this method overrides any value previously set using {@link #setBeanClass}. |
| | | * You must call either this method or {@link #setBeanClass} before {@link #create}. |
| | | * |
| | | * @param bean the initial bean |
| | | */ |
| | | public void setBean(Object bean) { |
| | | this.bean = bean; |
| | | if (bean != null) { |
| | | beanClass = bean.getClass(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Set the class of the bean that the generated map should support. |
| | | * You must call either this method or {@link #setBeanClass} before {@link #create}. |
| | | * |
| | | * @param beanClass the class of the bean |
| | | */ |
| | | public void setBeanClass(Class beanClass) { |
| | | this.beanClass = beanClass; |
| | | } |
| | | |
| | | /** |
| | | * Limit the properties reflected by the generated map. |
| | | * |
| | | * @param require any combination of {@link #REQUIRE_GETTER} and |
| | | * {@link #REQUIRE_SETTER}; default is zero (any property allowed) |
| | | */ |
| | | public void setRequire(int require) { |
| | | this.require = require; |
| | | } |
| | | |
| | | @Override |
| | | protected ClassLoader getDefaultClassLoader() { |
| | | return beanClass.getClassLoader(); |
| | | } |
| | | |
| | | @Override |
| | | protected ProtectionDomain getProtectionDomain() { |
| | | return ReflectUtils.getProtectionDomain(beanClass); |
| | | } |
| | | |
| | | /** |
| | | * Create a new instance of the <code>BeanMap</code>. An existing |
| | | * generated class will be reused if possible. |
| | | * |
| | | * @return {BladeBeanMap} |
| | | */ |
| | | public BladeBeanMap create() { |
| | | if (beanClass == null) { |
| | | throw new IllegalArgumentException("Class of bean unknown"); |
| | | } |
| | | setNamePrefix(beanClass.getName()); |
| | | BladeBeanMapKey key = new BladeBeanMapKey(beanClass, require); |
| | | return (BladeBeanMap) super.create(key); |
| | | } |
| | | |
| | | @Override |
| | | public void generateClass(ClassVisitor v) throws Exception { |
| | | new BladeBeanMapEmitter(v, getClassName(), beanClass, require); |
| | | } |
| | | |
| | | @Override |
| | | protected Object firstInstance(Class type) { |
| | | return ((BeanMap) ReflectUtils.newInstance(type)).newInstance(bean); |
| | | } |
| | | |
| | | @Override |
| | | protected Object nextInstance(Object instance) { |
| | | return ((BeanMap) instance).newInstance(bean); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.beans; |
| | | |
| | | import org.springblade.core.tool.utils.ReflectUtil; |
| | | import org.springframework.asm.ClassVisitor; |
| | | import org.springframework.asm.Label; |
| | | import org.springframework.asm.Type; |
| | | import org.springframework.cglib.core.*; |
| | | |
| | | import java.beans.PropertyDescriptor; |
| | | import java.util.HashMap; |
| | | import java.util.Iterator; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * éå cglib BeanMap å¤çå¨ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | class BladeBeanMapEmitter extends ClassEmitter { |
| | | private static final Type BEAN_MAP = TypeUtils.parseType(BladeBeanMap.class.getName()); |
| | | private static final Type FIXED_KEY_SET = TypeUtils.parseType("org.springframework.cglib.beans.FixedKeySet"); |
| | | private static final Signature CSTRUCT_OBJECT = TypeUtils.parseConstructor("Object"); |
| | | private static final Signature CSTRUCT_STRING_ARRAY = TypeUtils.parseConstructor("String[]"); |
| | | private static final Signature BEAN_MAP_GET = TypeUtils.parseSignature("Object get(Object, Object)"); |
| | | private static final Signature BEAN_MAP_PUT = TypeUtils.parseSignature("Object put(Object, Object, Object)"); |
| | | private static final Signature KEY_SET = TypeUtils.parseSignature("java.util.Set keySet()"); |
| | | private static final Signature NEW_INSTANCE = new Signature("newInstance", BEAN_MAP, new Type[]{Constants.TYPE_OBJECT}); |
| | | private static final Signature GET_PROPERTY_TYPE = TypeUtils.parseSignature("Class getPropertyType(String)"); |
| | | |
| | | public BladeBeanMapEmitter(ClassVisitor v, String className, Class type, int require) { |
| | | super(v); |
| | | |
| | | begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE); |
| | | EmitUtils.null_constructor(this); |
| | | EmitUtils.factory_method(this, NEW_INSTANCE); |
| | | generateConstructor(); |
| | | |
| | | Map<String, PropertyDescriptor> getters = makePropertyMap(ReflectUtil.getBeanGetters(type)); |
| | | Map<String, PropertyDescriptor> setters = makePropertyMap(ReflectUtil.getBeanSetters(type)); |
| | | Map<String, PropertyDescriptor> allProps = new HashMap<>(32); |
| | | allProps.putAll(getters); |
| | | allProps.putAll(setters); |
| | | |
| | | if (require != 0) { |
| | | for (Iterator it = allProps.keySet().iterator(); it.hasNext(); ) { |
| | | String name = (String) it.next(); |
| | | if ((((require & BladeBeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) || |
| | | (((require & BladeBeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) { |
| | | it.remove(); |
| | | getters.remove(name); |
| | | setters.remove(name); |
| | | } |
| | | } |
| | | } |
| | | generateGet(type, getters); |
| | | generatePut(type, setters); |
| | | |
| | | String[] allNames = getNames(allProps); |
| | | generateKeySet(allNames); |
| | | generateGetPropertyType(allProps, allNames); |
| | | end_class(); |
| | | } |
| | | |
| | | private Map<String, PropertyDescriptor> makePropertyMap(PropertyDescriptor[] props) { |
| | | Map<String, PropertyDescriptor> names = new HashMap<>(16); |
| | | for (PropertyDescriptor prop : props) { |
| | | String propName = prop.getName(); |
| | | // è¿æ»¤ getClassï¼Spring çå·¥å
·ç±»ä¼æ¿å°è¯¥æ¹æ³ |
| | | if (!"class".equals(propName)) { |
| | | names.put(propName, prop); |
| | | } |
| | | } |
| | | return names; |
| | | } |
| | | |
| | | private String[] getNames(Map<String, PropertyDescriptor> propertyMap) { |
| | | return propertyMap.keySet().toArray(new String[0]); |
| | | } |
| | | |
| | | private void generateConstructor() { |
| | | CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null); |
| | | e.load_this(); |
| | | e.load_arg(0); |
| | | e.super_invoke_constructor(CSTRUCT_OBJECT); |
| | | e.return_value(); |
| | | e.end_method(); |
| | | } |
| | | |
| | | private void generateGet(Class type, final Map<String, PropertyDescriptor> getters) { |
| | | final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null); |
| | | e.load_arg(0); |
| | | e.checkcast(Type.getType(type)); |
| | | e.load_arg(1); |
| | | e.checkcast(Constants.TYPE_STRING); |
| | | EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { |
| | | @Override |
| | | public void processCase(Object key, Label end) { |
| | | PropertyDescriptor pd = getters.get(key); |
| | | MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod()); |
| | | e.invoke(method); |
| | | e.box(method.getSignature().getReturnType()); |
| | | e.return_value(); |
| | | } |
| | | |
| | | @Override |
| | | public void processDefault() { |
| | | e.aconst_null(); |
| | | e.return_value(); |
| | | } |
| | | }); |
| | | e.end_method(); |
| | | } |
| | | |
| | | private void generatePut(Class type, final Map<String, PropertyDescriptor> setters) { |
| | | final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null); |
| | | e.load_arg(0); |
| | | e.checkcast(Type.getType(type)); |
| | | e.load_arg(1); |
| | | e.checkcast(Constants.TYPE_STRING); |
| | | EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { |
| | | @Override |
| | | public void processCase(Object key, Label end) { |
| | | PropertyDescriptor pd = setters.get(key); |
| | | if (pd.getReadMethod() == null) { |
| | | e.aconst_null(); |
| | | } else { |
| | | MethodInfo read = ReflectUtils.getMethodInfo(pd.getReadMethod()); |
| | | e.dup(); |
| | | e.invoke(read); |
| | | e.box(read.getSignature().getReturnType()); |
| | | } |
| | | // move old value behind bean |
| | | e.swap(); |
| | | // new value |
| | | e.load_arg(2); |
| | | MethodInfo write = ReflectUtils.getMethodInfo(pd.getWriteMethod()); |
| | | e.unbox(write.getSignature().getArgumentTypes()[0]); |
| | | e.invoke(write); |
| | | e.return_value(); |
| | | } |
| | | |
| | | @Override |
| | | public void processDefault() { |
| | | // fall-through |
| | | } |
| | | }); |
| | | e.aconst_null(); |
| | | e.return_value(); |
| | | e.end_method(); |
| | | } |
| | | |
| | | private void generateKeySet(String[] allNames) { |
| | | // static initializer |
| | | declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null); |
| | | |
| | | CodeEmitter e = begin_static(); |
| | | e.new_instance(FIXED_KEY_SET); |
| | | e.dup(); |
| | | EmitUtils.push_array(e, allNames); |
| | | e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY); |
| | | e.putfield("keys"); |
| | | e.return_value(); |
| | | e.end_method(); |
| | | |
| | | // keySet |
| | | e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null); |
| | | e.load_this(); |
| | | e.getfield("keys"); |
| | | e.return_value(); |
| | | e.end_method(); |
| | | } |
| | | |
| | | private void generateGetPropertyType(final Map allProps, String[] allNames) { |
| | | final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null); |
| | | e.load_arg(0); |
| | | EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() { |
| | | @Override |
| | | public void processCase(Object key, Label end) { |
| | | PropertyDescriptor pd = (PropertyDescriptor) allProps.get(key); |
| | | EmitUtils.load_class(e, Type.getType(pd.getPropertyType())); |
| | | e.return_value(); |
| | | } |
| | | |
| | | @Override |
| | | public void processDefault() { |
| | | e.aconst_null(); |
| | | e.return_value(); |
| | | } |
| | | }); |
| | | e.end_method(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.beans; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * bean map keyï¼æé«æ§è½ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @EqualsAndHashCode |
| | | @AllArgsConstructor |
| | | public class BladeBeanMapKey { |
| | | private final Class type; |
| | | private final int require; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.beans; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * copy åæ®µ é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Target(ElementType.FIELD) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | public @interface CopyProperty { |
| | | |
| | | /** |
| | | * 屿§åï¼ç¨äºæå®å«åï¼é»è®¤ä½¿ç¨ï¼field name |
| | | * @return 屿§å |
| | | */ |
| | | String value() default ""; |
| | | |
| | | /** |
| | | * 忽ç¥ï¼é»è®¤ä¸º false |
| | | * @return æ¯å¦å¿½ç¥ |
| | | */ |
| | | boolean ignore() default false; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.config; |
| | | |
| | | import org.springblade.core.tool.convert.EnumToStringConverter; |
| | | import org.springblade.core.tool.convert.StringToEnumConverter; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.format.FormatterRegistry; |
| | | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
| | | |
| | | /** |
| | | * blade enum ã-ã String 转æ¢é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AutoConfiguration |
| | | public class BladeConverterConfiguration implements WebMvcConfigurer { |
| | | |
| | | @Override |
| | | public void addFormatters(FormatterRegistry registry) { |
| | | registry.addConverter(new EnumToStringConverter()); |
| | | registry.addConverter(new StringToEnumConverter()); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.config; |
| | | |
| | | import com.fasterxml.jackson.core.json.JsonReadFeature; |
| | | import com.fasterxml.jackson.databind.DeserializationFeature; |
| | | import com.fasterxml.jackson.databind.MapperFeature; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.fasterxml.jackson.databind.SerializationFeature; |
| | | import org.springblade.core.tool.jackson.BladeJacksonProperties; |
| | | import org.springblade.core.tool.jackson.BladeJavaTimeModule; |
| | | import org.springblade.core.tool.utils.DateUtil; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.ZoneId; |
| | | import java.util.Locale; |
| | | import java.util.TimeZone; |
| | | |
| | | /** |
| | | * Jacksoné
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AutoConfiguration(before = JacksonAutoConfiguration.class) |
| | | @ConditionalOnClass(ObjectMapper.class) |
| | | @EnableConfigurationProperties(BladeJacksonProperties.class) |
| | | public class JacksonConfiguration { |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { |
| | | builder.simpleDateFormat(DateUtil.PATTERN_DATETIME); |
| | | //å建ObjectMapper |
| | | ObjectMapper objectMapper = builder.createXmlMapper(false).build(); |
| | | //设置å°ç¹ä¸ºä¸å½ |
| | | objectMapper.setLocale(Locale.CHINA); |
| | | //廿é»è®¤çæ¶é´æ³æ ¼å¼ |
| | | objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); |
| | | //设置为ä¸å½ä¸æµ·æ¶åº |
| | | objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault())); |
| | | //åºååæ¶ï¼æ¥æçç»ä¸æ ¼å¼ |
| | | objectMapper.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_DATETIME, Locale.CHINA)); |
| | | //åºååå¤ç |
| | | objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true); |
| | | objectMapper.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true); |
| | | //失败å¤ç |
| | | objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); |
| | | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
| | | //åå¼å·å¤ç |
| | | objectMapper.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature(), true); |
| | | //ååºååæ¶ï¼å±æ§ä¸åå¨çå
¼å®¹å¤ç |
| | | objectMapper.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); |
| | | //æ¥ææ ¼å¼å |
| | | objectMapper.configure(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS, false); |
| | | objectMapper.registerModule(BladeJavaTimeModule.INSTANCE); |
| | | objectMapper.configure(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS, true); |
| | | objectMapper.findAndRegisterModules(); |
| | | return objectMapper; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.config; |
| | | |
| | | |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springblade.core.tool.jackson.BladeJacksonProperties; |
| | | import org.springblade.core.tool.jackson.MappingApiJackson2HttpMessageConverter; |
| | | import org.springblade.core.tool.utils.DateUtil; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.core.Ordered; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.format.FormatterRegistry; |
| | | import org.springframework.format.datetime.DateFormatter; |
| | | import org.springframework.http.converter.*; |
| | | import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; |
| | | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
| | | |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * æ¶æ¯é
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AutoConfiguration |
| | | @AllArgsConstructor |
| | | @Order(Ordered.HIGHEST_PRECEDENCE) |
| | | public class MessageConfiguration implements WebMvcConfigurer { |
| | | |
| | | private final ObjectMapper objectMapper; |
| | | private final BladeJacksonProperties properties; |
| | | |
| | | /** |
| | | * ä½¿ç¨ JACKSON ä½ä¸ºJSON MessageConverter |
| | | * æ¶æ¯è½¬æ¢ï¼å
ç½®æç¹ç»ä¼ ï¼ä¸è½½åå符串 |
| | | */ |
| | | @Override |
| | | public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { |
| | | converters.removeIf(x -> x instanceof StringHttpMessageConverter || x instanceof AbstractJackson2HttpMessageConverter); |
| | | converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8)); |
| | | converters.add(new ByteArrayHttpMessageConverter()); |
| | | converters.add(new ResourceHttpMessageConverter()); |
| | | converters.add(new ResourceRegionHttpMessageConverter()); |
| | | converters.add(new MappingApiJackson2HttpMessageConverter(objectMapper, properties)); |
| | | } |
| | | |
| | | /** |
| | | * æ¥ææ ¼å¼å |
| | | */ |
| | | @Override |
| | | public void addFormatters(FormatterRegistry registry) { |
| | | registry.addFormatter(new DateFormatter(DateUtil.PATTERN_DATE)); |
| | | registry.addFormatter(new DateFormatter(DateUtil.PATTERN_DATETIME)); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.config; |
| | | |
| | | |
| | | import org.springblade.core.tool.support.BinderSupplier; |
| | | import org.springblade.core.tool.utils.SpringUtil; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | import java.util.function.Supplier; |
| | | |
| | | /** |
| | | * å·¥å
·é
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AutoConfiguration |
| | | public class ToolConfiguration { |
| | | |
| | | /** |
| | | * Springä¸ä¸æç¼å |
| | | */ |
| | | @Bean |
| | | public SpringUtil springUtil() { |
| | | return new SpringUtil(); |
| | | } |
| | | |
| | | /** |
| | | * Binderæ¯æç±» |
| | | */ |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public Supplier<Object> binderSupplier() { |
| | | return new BinderSupplier(); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.constant; |
| | | |
| | | /** |
| | | * ç³»ç»å¸¸é |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface BladeConstant { |
| | | |
| | | /** |
| | | * ç¼ç |
| | | */ |
| | | String UTF_8 = "UTF-8"; |
| | | |
| | | /** |
| | | * contentType |
| | | */ |
| | | String CONTENT_TYPE_NAME = "Content-type"; |
| | | |
| | | /** |
| | | * JSON èµæº |
| | | */ |
| | | String CONTENT_TYPE = "application/json;charset=utf-8"; |
| | | |
| | | /** |
| | | * ä¸ä¸æé®å¼ |
| | | */ |
| | | String CONTEXT_KEY = "bladeContext"; |
| | | |
| | | /** |
| | | * mdc request id key |
| | | */ |
| | | String MDC_REQUEST_ID_KEY = "requestId"; |
| | | |
| | | /** |
| | | * mdc account id key |
| | | */ |
| | | String MDC_ACCOUNT_ID_KEY = "accountId"; |
| | | |
| | | /** |
| | | * mdc tenant id key |
| | | */ |
| | | String MDC_TENANT_ID_KEY = "tenantId"; |
| | | |
| | | /** |
| | | * è§è²åç¼ |
| | | */ |
| | | String SECURITY_ROLE_PREFIX = "ROLE_"; |
| | | |
| | | /** |
| | | * 主é®å段å |
| | | */ |
| | | String DB_PRIMARY_KEY = "id"; |
| | | |
| | | /** |
| | | * 主é®å段getæ¹æ³ |
| | | */ |
| | | String DB_PRIMARY_KEY_METHOD = "getId"; |
| | | |
| | | /** |
| | | * ç§æ·å段å |
| | | */ |
| | | String DB_TENANT_KEY = "tenantId"; |
| | | |
| | | /** |
| | | * ç§æ·å段getæ¹æ³ |
| | | */ |
| | | String DB_TENANT_KEY_GET_METHOD = "getTenantId"; |
| | | |
| | | /** |
| | | * ç§æ·å段setæ¹æ³ |
| | | */ |
| | | String DB_TENANT_KEY_SET_METHOD = "setTenantId"; |
| | | |
| | | /** |
| | | * ä¸å¡ç¶æ[1:æ£å¸¸] |
| | | */ |
| | | int DB_STATUS_NORMAL = 1; |
| | | |
| | | |
| | | /** |
| | | * å é¤ç¶æ[0:æ£å¸¸,1:å é¤] |
| | | */ |
| | | int DB_NOT_DELETED = 0; |
| | | int DB_IS_DELETED = 1; |
| | | |
| | | /** |
| | | * ç¨æ·éå®ç¶æ |
| | | */ |
| | | int DB_ADMIN_NON_LOCKED = 0; |
| | | int DB_ADMIN_LOCKED = 1; |
| | | |
| | | /** |
| | | * 顶级ç¶èç¹id |
| | | */ |
| | | Long TOP_PARENT_ID = 0L; |
| | | |
| | | /** |
| | | * 顶级ç¶èç¹åç§° |
| | | */ |
| | | String TOP_PARENT_NAME = "顶级"; |
| | | |
| | | /** |
| | | * 管çå对åºçç§æ·ID |
| | | */ |
| | | String ADMIN_TENANT_ID = "000000"; |
| | | |
| | | /** |
| | | * æ¥å¿é»è®¤ç¶æ |
| | | */ |
| | | String LOG_NORMAL_TYPE = "1"; |
| | | |
| | | /** |
| | | * é»è®¤ä¸ºç©ºæ¶æ¯ |
| | | */ |
| | | String DEFAULT_NULL_MESSAGE = "ææ æ¿è½½æ°æ®"; |
| | | /** |
| | | * é»è®¤æåæ¶æ¯ |
| | | */ |
| | | String DEFAULT_SUCCESS_MESSAGE = "æä½æå"; |
| | | /** |
| | | * é»è®¤å¤±è´¥æ¶æ¯ |
| | | */ |
| | | String DEFAULT_FAILURE_MESSAGE = "æä½å¤±è´¥"; |
| | | /** |
| | | * é»è®¤æªæææ¶æ¯ |
| | | */ |
| | | String DEFAULT_UNAUTHORIZED_MESSAGE = "ç¾å认è¯å¤±è´¥"; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.constant; |
| | | |
| | | /** |
| | | * ç³»ç»é»è®¤è§è² |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class RoleConstant { |
| | | |
| | | public static final String ADMINISTRATOR = "administrator"; |
| | | |
| | | public static final String HAS_ROLE_ADMINISTRATOR = "hasRole('" + ADMINISTRATOR + "')"; |
| | | |
| | | public static final String ADMIN = "admin"; |
| | | |
| | | public static final String HAS_ROLE_ADMIN = "hasAnyRole('" + ADMINISTRATOR + "', '" + ADMIN + "')"; |
| | | |
| | | public static final String USER = "user"; |
| | | |
| | | public static final String HAS_ROLE_USER = "hasRole('" + USER + "')"; |
| | | |
| | | public static final String TEST = "test"; |
| | | |
| | | public static final String HAS_ROLE_TEST = "hasRole('" + TEST + "')"; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.convert; |
| | | |
| | | import org.springframework.boot.convert.ApplicationConversionService; |
| | | import org.springframework.core.convert.support.GenericConversionService; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.util.StringValueResolver; |
| | | |
| | | /** |
| | | * ç±»å è½¬æ¢ æå¡ï¼æ·»å äº IEnum è½¬æ¢ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeConversionService extends ApplicationConversionService { |
| | | @Nullable |
| | | private static volatile BladeConversionService SHARED_INSTANCE; |
| | | |
| | | public BladeConversionService() { |
| | | this(null); |
| | | } |
| | | |
| | | public BladeConversionService(@Nullable StringValueResolver embeddedValueResolver) { |
| | | super(embeddedValueResolver); |
| | | super.addConverter(new EnumToStringConverter()); |
| | | super.addConverter(new StringToEnumConverter()); |
| | | } |
| | | |
| | | /** |
| | | * Return a shared default application {@code ConversionService} instance, lazily |
| | | * building it once needed. |
| | | * <p> |
| | | * Note: This method actually returns an {@link BladeConversionService} |
| | | * instance. However, the {@code ConversionService} signature has been preserved for |
| | | * binary compatibility. |
| | | * @return the shared {@code BladeConversionService} instance (never{@code null}) |
| | | */ |
| | | public static GenericConversionService getInstance() { |
| | | BladeConversionService sharedInstance = BladeConversionService.SHARED_INSTANCE; |
| | | if (sharedInstance == null) { |
| | | synchronized (BladeConversionService.class) { |
| | | sharedInstance = BladeConversionService.SHARED_INSTANCE; |
| | | if (sharedInstance == null) { |
| | | sharedInstance = new BladeConversionService(); |
| | | BladeConversionService.SHARED_INSTANCE = sharedInstance; |
| | | } |
| | | } |
| | | } |
| | | return sharedInstance; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.convert; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.tool.function.CheckedFunction; |
| | | import org.springblade.core.tool.utils.ClassUtil; |
| | | import org.springblade.core.tool.utils.ConvertUtil; |
| | | import org.springblade.core.tool.utils.ReflectUtil; |
| | | import org.springblade.core.tool.utils.Unchecked; |
| | | import org.springframework.cglib.core.Converter; |
| | | import org.springframework.core.convert.TypeDescriptor; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ConcurrentMap; |
| | | |
| | | /** |
| | | * ç»å spring cglib Converter å spring ConversionService |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | @AllArgsConstructor |
| | | public class BladeConverter implements Converter { |
| | | private static final ConcurrentMap<String, TypeDescriptor> TYPE_CACHE = new ConcurrentHashMap<>(); |
| | | private final Class<?> sourceClazz; |
| | | private final Class<?> targetClazz; |
| | | |
| | | /** |
| | | * cglib convert |
| | | * |
| | | * @param value æºå¯¹è±¡å±æ§ |
| | | * @param target ç®æ å¯¹è±¡å±æ§ç±» |
| | | * @param fieldName ç®æ çfieldåï¼å为 set æ¹æ³åï¼BladeBeanCopier éåäºæ´æ¹ |
| | | * @return {Object} |
| | | */ |
| | | @Override |
| | | @Nullable |
| | | public Object convert(Object value, Class target, final Object fieldName) { |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | // ç±»å䏿 ·ï¼ä¸éè¦è½¬æ¢ |
| | | if (ClassUtil.isAssignableValue(target, value)) { |
| | | return value; |
| | | } |
| | | try { |
| | | TypeDescriptor targetDescriptor = BladeConverter.getTypeDescriptor(targetClazz, (String) fieldName); |
| | | // 1. 夿 sourceClazz 为 Map |
| | | if (Map.class.isAssignableFrom(sourceClazz)) { |
| | | return ConvertUtil.convert(value, targetDescriptor); |
| | | } else { |
| | | TypeDescriptor sourceDescriptor = BladeConverter.getTypeDescriptor(sourceClazz, (String) fieldName); |
| | | return ConvertUtil.convert(value, sourceDescriptor, targetDescriptor); |
| | | } |
| | | } catch (Throwable e) { |
| | | log.warn("BladeConverter error", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private static TypeDescriptor getTypeDescriptor(final Class<?> clazz, final String fieldName) { |
| | | String srcCacheKey = clazz.getName() + fieldName; |
| | | // å¿½ç¥æåºå¼å¸¸ç彿°ï¼å®ä¹å®æ´æ³åï¼é¿å
ç¼è¯é®é¢ |
| | | CheckedFunction<String, TypeDescriptor> uncheckedFunction = (key) -> { |
| | | // è¿é property ç论ä¸ä¸ä¼ä¸º null |
| | | Field field = ReflectUtil.getField(clazz, fieldName); |
| | | if (field == null) { |
| | | throw new NoSuchFieldException(fieldName); |
| | | } |
| | | return new TypeDescriptor(field); |
| | | }; |
| | | return TYPE_CACHE.computeIfAbsent(srcCacheKey, Unchecked.function(uncheckedFunction)); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.convert; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonValue; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.tool.utils.ConvertUtil; |
| | | import org.springframework.core.convert.TypeDescriptor; |
| | | import org.springframework.core.convert.converter.ConditionalGenericConverter; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.lang.reflect.AccessibleObject; |
| | | import java.lang.reflect.Field; |
| | | import java.lang.reflect.InvocationTargetException; |
| | | import java.lang.reflect.Method; |
| | | import java.util.Collections; |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ConcurrentMap; |
| | | |
| | | /** |
| | | * æ¥æ¶åæ° å jackson Enum -ã String è½¬æ¢ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | public class EnumToStringConverter implements ConditionalGenericConverter { |
| | | /** |
| | | * ç¼å Enum 类信æ¯ï¼æä¾æ§è½ |
| | | */ |
| | | private static final ConcurrentMap<Class<?>, AccessibleObject> ENUM_CACHE_MAP = new ConcurrentHashMap<>(8); |
| | | |
| | | @Nullable |
| | | private static AccessibleObject getAnnotation(Class<?> clazz) { |
| | | Set<AccessibleObject> accessibleObjects = new HashSet<>(); |
| | | // JsonValue METHOD, FIELD |
| | | Field[] fields = clazz.getDeclaredFields(); |
| | | Collections.addAll(accessibleObjects, fields); |
| | | // methods |
| | | Method[] methods = clazz.getDeclaredMethods(); |
| | | Collections.addAll(accessibleObjects, methods); |
| | | for (AccessibleObject accessibleObject : accessibleObjects) { |
| | | // å¤ç¨ jackson ç JsonValue 注解 |
| | | JsonValue jsonValue = accessibleObject.getAnnotation(JsonValue.class); |
| | | if (jsonValue != null && jsonValue.value()) { |
| | | accessibleObject.setAccessible(true); |
| | | return accessibleObject; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public Set<ConvertiblePair> getConvertibleTypes() { |
| | | Set<ConvertiblePair> pairSet = new HashSet<>(3); |
| | | pairSet.add(new ConvertiblePair(Enum.class, String.class)); |
| | | pairSet.add(new ConvertiblePair(Enum.class, Integer.class)); |
| | | pairSet.add(new ConvertiblePair(Enum.class, Long.class)); |
| | | return Collections.unmodifiableSet(pairSet); |
| | | } |
| | | |
| | | @Override |
| | | public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | Class<?> sourceClazz = sourceType.getType(); |
| | | AccessibleObject accessibleObject = ENUM_CACHE_MAP.computeIfAbsent(sourceClazz, EnumToStringConverter::getAnnotation); |
| | | Class<?> targetClazz = targetType.getType(); |
| | | // å¦æä¸ºnullï¼èµ°é»è®¤çè½¬æ¢ |
| | | if (accessibleObject == null) { |
| | | if (String.class == targetClazz) { |
| | | return ((Enum) source).name(); |
| | | } |
| | | int ordinal = ((Enum) source).ordinal(); |
| | | return ConvertUtil.convert(ordinal, targetClazz); |
| | | } |
| | | try { |
| | | return EnumToStringConverter.invoke(sourceClazz, accessibleObject, source, targetClazz); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Nullable |
| | | private static Object invoke(Class<?> clazz, AccessibleObject accessibleObject, Object source, Class<?> targetClazz) |
| | | throws IllegalAccessException, InvocationTargetException { |
| | | Object value = null; |
| | | if (accessibleObject instanceof Field) { |
| | | Field field = (Field) accessibleObject; |
| | | value = field.get(source); |
| | | } else if (accessibleObject instanceof Method) { |
| | | Method method = (Method) accessibleObject; |
| | | Class<?> paramType = method.getParameterTypes()[0]; |
| | | // ç±»åè½¬æ¢ |
| | | Object object = ConvertUtil.convert(source, paramType); |
| | | value = method.invoke(clazz, object); |
| | | } |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | return ConvertUtil.convert(value, targetClazz); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.convert; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonCreator; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.tool.utils.ConvertUtil; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springframework.core.convert.TypeDescriptor; |
| | | import org.springframework.core.convert.converter.ConditionalGenericConverter; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.lang.reflect.AccessibleObject; |
| | | import java.lang.reflect.Constructor; |
| | | import java.lang.reflect.InvocationTargetException; |
| | | import java.lang.reflect.Method; |
| | | import java.util.Collections; |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ConcurrentMap; |
| | | |
| | | /** |
| | | * æ¥æ¶åæ° å jackson String -ã Enum è½¬æ¢ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | public class StringToEnumConverter implements ConditionalGenericConverter { |
| | | /** |
| | | * ç¼å Enum 类信æ¯ï¼æä¾æ§è½ |
| | | */ |
| | | private static final ConcurrentMap<Class<?>, AccessibleObject> ENUM_CACHE_MAP = new ConcurrentHashMap<>(8); |
| | | |
| | | @Nullable |
| | | private static AccessibleObject getAnnotation(Class<?> clazz) { |
| | | Set<AccessibleObject> accessibleObjects = new HashSet<>(); |
| | | // JsonCreator METHOD, CONSTRUCTOR |
| | | Constructor<?>[] constructors = clazz.getConstructors(); |
| | | Collections.addAll(accessibleObjects, constructors); |
| | | // methods |
| | | Method[] methods = clazz.getDeclaredMethods(); |
| | | Collections.addAll(accessibleObjects, methods); |
| | | for (AccessibleObject accessibleObject : accessibleObjects) { |
| | | // å¤ç¨ jackson ç JsonCreator注解 |
| | | JsonCreator jsonCreator = accessibleObject.getAnnotation(JsonCreator.class); |
| | | if (jsonCreator != null && JsonCreator.Mode.DISABLED != jsonCreator.mode()) { |
| | | accessibleObject.setAccessible(true); |
| | | return accessibleObject; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public Set<ConvertiblePair> getConvertibleTypes() { |
| | | return Collections.singleton(new ConvertiblePair(String.class, Enum.class)); |
| | | } |
| | | |
| | | @Nullable |
| | | @Override |
| | | public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { |
| | | if (StringUtil.isBlank((String) source)) { |
| | | return null; |
| | | } |
| | | Class<?> clazz = targetType.getType(); |
| | | AccessibleObject accessibleObject = ENUM_CACHE_MAP.computeIfAbsent(clazz, StringToEnumConverter::getAnnotation); |
| | | String value = ((String) source).trim(); |
| | | // å¦æä¸ºnullï¼èµ°é»è®¤çè½¬æ¢ |
| | | if (accessibleObject == null) { |
| | | return valueOf(clazz, value); |
| | | } |
| | | try { |
| | | return StringToEnumConverter.invoke(clazz, accessibleObject, value); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @SuppressWarnings("unchecked") |
| | | private static <T extends Enum<T>> T valueOf(Class<?> clazz, String value){ |
| | | return Enum.valueOf((Class<T>) clazz, value); |
| | | } |
| | | |
| | | @Nullable |
| | | private static Object invoke(Class<?> clazz, AccessibleObject accessibleObject, String value) |
| | | throws IllegalAccessException, InvocationTargetException, InstantiationException { |
| | | if (accessibleObject instanceof Constructor) { |
| | | Constructor constructor = (Constructor) accessibleObject; |
| | | Class<?> paramType = constructor.getParameterTypes()[0]; |
| | | // ç±»åè½¬æ¢ |
| | | Object object = ConvertUtil.convert(value, paramType); |
| | | return constructor.newInstance(object); |
| | | } |
| | | if (accessibleObject instanceof Method) { |
| | | Method method = (Method) accessibleObject; |
| | | Class<?> paramType = method.getParameterTypes()[0]; |
| | | // ç±»åè½¬æ¢ |
| | | Object object = ConvertUtil.convert(value, paramType); |
| | | return method.invoke(clazz, object); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.function; |
| | | |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | /** |
| | | * 忣ç Callable |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @FunctionalInterface |
| | | public interface CheckedCallable<T> { |
| | | |
| | | /** |
| | | * Run this callable. |
| | | * |
| | | * @return result |
| | | * @throws Throwable CheckedException |
| | | */ |
| | | @Nullable |
| | | T call() throws Throwable; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.function; |
| | | |
| | | /** |
| | | * 忣ç Comparator |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @FunctionalInterface |
| | | public interface CheckedComparator<T> { |
| | | |
| | | /** |
| | | * Compares its two arguments for order. |
| | | * |
| | | * @param o1 o1 |
| | | * @param o2 o2 |
| | | * @return int |
| | | * @throws Throwable CheckedException |
| | | */ |
| | | int compare(T o1, T o2) throws Throwable; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.function; |
| | | |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | /** |
| | | * 忣ç Consumer |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @FunctionalInterface |
| | | public interface CheckedConsumer<T> { |
| | | |
| | | /** |
| | | * Run the Consumer |
| | | * |
| | | * @param t T |
| | | * @throws Throwable UncheckedException |
| | | */ |
| | | @Nullable |
| | | void accept(@Nullable T t) throws Throwable; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.function; |
| | | |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | /** |
| | | * 忣ç function |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @FunctionalInterface |
| | | public interface CheckedFunction<T, R> { |
| | | |
| | | /** |
| | | * Run the Function |
| | | * |
| | | * @param t T |
| | | * @return R R |
| | | * @throws Throwable CheckedException |
| | | */ |
| | | @Nullable |
| | | R apply(@Nullable T t) throws Throwable; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.function; |
| | | |
| | | /** |
| | | * 忣ç runnable |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @FunctionalInterface |
| | | public interface CheckedRunnable { |
| | | |
| | | /** |
| | | * Run this runnable. |
| | | * |
| | | * @throws Throwable CheckedException |
| | | */ |
| | | void run() throws Throwable; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.function; |
| | | |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | /** |
| | | * 忣ç Supplier |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @FunctionalInterface |
| | | public interface CheckedSupplier<T> { |
| | | |
| | | /** |
| | | * Run the Supplier |
| | | * |
| | | * @return T |
| | | * @throws Throwable CheckedException |
| | | */ |
| | | @Nullable |
| | | T get() throws Throwable; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.jackson; |
| | | |
| | | import com.fasterxml.jackson.core.JsonEncoding; |
| | | import com.fasterxml.jackson.core.JsonGenerator; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.core.PrettyPrinter; |
| | | import com.fasterxml.jackson.core.util.DefaultIndenter; |
| | | import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; |
| | | import com.fasterxml.jackson.databind.*; |
| | | import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; |
| | | import com.fasterxml.jackson.databind.ser.FilterProvider; |
| | | import org.springblade.core.tool.utils.Charsets; |
| | | import org.springframework.http.HttpOutputMessage; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.http.converter.HttpMessageConversionException; |
| | | import org.springframework.http.converter.HttpMessageNotWritableException; |
| | | import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; |
| | | import org.springframework.http.converter.json.MappingJacksonValue; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.util.TypeUtils; |
| | | |
| | | import java.io.IOException; |
| | | import java.lang.reflect.Type; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.concurrent.atomic.AtomicReference; |
| | | |
| | | /** |
| | | * å读åç json æ¶æ¯ å¤çå¨ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public abstract class AbstractReadWriteJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter { |
| | | private static final java.nio.charset.Charset DEFAULT_CHARSET = Charsets.UTF_8; |
| | | |
| | | private final ObjectMapper writeObjectMapper; |
| | | @Nullable |
| | | private PrettyPrinter ssePrettyPrinter; |
| | | |
| | | public AbstractReadWriteJackson2HttpMessageConverter(ObjectMapper readObjectMapper, ObjectMapper writeObjectMapper) { |
| | | super(readObjectMapper); |
| | | this.writeObjectMapper = writeObjectMapper; |
| | | initSsePrettyPrinter(); |
| | | } |
| | | |
| | | public AbstractReadWriteJackson2HttpMessageConverter(ObjectMapper readObjectMapper, ObjectMapper writeObjectMapper, MediaType supportedMediaType) { |
| | | this(readObjectMapper, writeObjectMapper); |
| | | setSupportedMediaTypes(Collections.singletonList(supportedMediaType)); |
| | | initSsePrettyPrinter(); |
| | | } |
| | | |
| | | public AbstractReadWriteJackson2HttpMessageConverter(ObjectMapper readObjectMapper, ObjectMapper writeObjectMapper, List<MediaType> supportedMediaTypes) { |
| | | this(readObjectMapper, writeObjectMapper); |
| | | setSupportedMediaTypes(supportedMediaTypes); |
| | | } |
| | | |
| | | private void initSsePrettyPrinter() { |
| | | setDefaultCharset(DEFAULT_CHARSET); |
| | | DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter(); |
| | | prettyPrinter.indentObjectsWith(new DefaultIndenter(" ", "\ndata:")); |
| | | this.ssePrettyPrinter = prettyPrinter; |
| | | } |
| | | |
| | | @Override |
| | | public boolean canWrite(@NonNull Class<?> clazz, @Nullable MediaType mediaType) { |
| | | if (!canWrite(mediaType)) { |
| | | return false; |
| | | } |
| | | AtomicReference<Throwable> causeRef = new AtomicReference<>(); |
| | | if (this.defaultObjectMapper.canSerialize(clazz, causeRef)) { |
| | | return true; |
| | | } |
| | | logWarningIfNecessary(clazz, causeRef.get()); |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | protected void writeInternal(@NonNull Object object, @Nullable Type type, HttpOutputMessage outputMessage) |
| | | throws IOException, HttpMessageNotWritableException { |
| | | |
| | | MediaType contentType = outputMessage.getHeaders().getContentType(); |
| | | JsonEncoding encoding = getJsonEncoding(contentType); |
| | | JsonGenerator generator = this.writeObjectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding); |
| | | try { |
| | | writePrefix(generator, object); |
| | | |
| | | Object value = object; |
| | | Class<?> serializationView = null; |
| | | FilterProvider filters = null; |
| | | JavaType javaType = null; |
| | | |
| | | if (object instanceof MappingJacksonValue) { |
| | | MappingJacksonValue container = (MappingJacksonValue) object; |
| | | value = container.getValue(); |
| | | serializationView = container.getSerializationView(); |
| | | filters = container.getFilters(); |
| | | } |
| | | if (type != null && TypeUtils.isAssignable(type, value.getClass())) { |
| | | javaType = getJavaType(type, null); |
| | | } |
| | | |
| | | ObjectWriter objectWriter = (serializationView != null ? |
| | | this.writeObjectMapper.writerWithView(serializationView) : this.writeObjectMapper.writer()); |
| | | if (filters != null) { |
| | | objectWriter = objectWriter.with(filters); |
| | | } |
| | | if (javaType != null && javaType.isContainerType()) { |
| | | objectWriter = objectWriter.forType(javaType); |
| | | } |
| | | SerializationConfig config = objectWriter.getConfig(); |
| | | if (contentType != null && contentType.isCompatibleWith(MediaType.TEXT_EVENT_STREAM) && |
| | | config.isEnabled(SerializationFeature.INDENT_OUTPUT)) { |
| | | objectWriter = objectWriter.with(this.ssePrettyPrinter); |
| | | } |
| | | objectWriter.writeValue(generator, value); |
| | | |
| | | writeSuffix(generator, object); |
| | | generator.flush(); |
| | | } catch (InvalidDefinitionException ex) { |
| | | throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex); |
| | | } catch (JsonProcessingException ex) { |
| | | throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getOriginalMessage(), ex); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.jackson; |
| | | |
| | | import com.fasterxml.jackson.core.JsonGenerator; |
| | | import com.fasterxml.jackson.databind.SerializerProvider; |
| | | import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; |
| | | import com.fasterxml.jackson.databind.ser.std.NumberSerializer; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * 大æ°å¼åºååï¼é¿å
è¶
è¿jsç精度ï¼é æç²¾åº¦ä¸¢å¤± |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @JacksonStdImpl |
| | | public class BigNumberSerializer extends NumberSerializer { |
| | | |
| | | /** |
| | | * js æå¤§å¼ä¸º Math.pow(2, 53)ï¼åè¿å¶ä¸ºï¼9007199254740992 |
| | | */ |
| | | private static final long JS_NUM_MAX = 0x20000000000000L; |
| | | /** |
| | | * js æå°å¼ä¸º -Math.pow(2, 53)ï¼åè¿å¶ä¸ºï¼-9007199254740992 |
| | | */ |
| | | private static final long JS_NUM_MIN = -0x20000000000000L; |
| | | /** |
| | | * Static instance that is only to be used for {@link java.lang.Number}. |
| | | */ |
| | | public final static BigNumberSerializer instance = new BigNumberSerializer(Number.class); |
| | | |
| | | public BigNumberSerializer(Class<? extends Number> rawType) { |
| | | super(rawType); |
| | | } |
| | | |
| | | @Override |
| | | public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { |
| | | long longValue = value.longValue(); |
| | | if (longValue < JS_NUM_MIN || longValue > JS_NUM_MAX) { |
| | | gen.writeString(value.toString()); |
| | | } else { |
| | | super.serialize(value, gen, provider); |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.jackson; |
| | | |
| | | import com.fasterxml.jackson.core.JsonGenerator; |
| | | import com.fasterxml.jackson.databind.*; |
| | | import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; |
| | | import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | |
| | | import java.io.IOException; |
| | | import java.time.OffsetDateTime; |
| | | import java.time.temporal.TemporalAccessor; |
| | | import java.util.Collection; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * jackson é»è®¤å¼ä¸º null æ¶çå¤ç |
| | | * <p> |
| | | * ä¸»è¦æ¯ä¸ºäºé¿å
app 端åºç°null导è´éªé |
| | | * <p> |
| | | * è§åï¼ |
| | | * number -1 |
| | | * string "" |
| | | * date "" |
| | | * boolean false |
| | | * array [] |
| | | * Object {} |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeBeanSerializerModifier extends BeanSerializerModifier { |
| | | @Override |
| | | public List<BeanPropertyWriter> changeProperties( |
| | | SerializationConfig config, BeanDescription beanDesc, |
| | | List<BeanPropertyWriter> beanProperties) { |
| | | // å¾ªç¯ææçbeanPropertyWriter |
| | | beanProperties.forEach(writer -> { |
| | | // å¦æå·²ç»æ null åºååå¤ç妿³¨è§£ï¼@JsonSerialize(nullsUsing = xxx) è·³è¿ |
| | | if (writer.hasNullSerializer()) { |
| | | return; |
| | | } |
| | | JavaType type = writer.getType(); |
| | | Class<?> clazz = type.getRawClass(); |
| | | if (type.isTypeOrSubTypeOf(Number.class)) { |
| | | // writer.assignNullSerializer(NullJsonSerializers.NUMBER_JSON_SERIALIZER); |
| | | } else if (type.isTypeOrSubTypeOf(Boolean.class)) { |
| | | writer.assignNullSerializer(NullJsonSerializers.BOOLEAN_JSON_SERIALIZER); |
| | | } else if (type.isTypeOrSubTypeOf(Character.class)) { |
| | | writer.assignNullSerializer(NullJsonSerializers.STRING_JSON_SERIALIZER); |
| | | } else if (type.isTypeOrSubTypeOf(String.class)) { |
| | | writer.assignNullSerializer(NullJsonSerializers.STRING_JSON_SERIALIZER); |
| | | } else if (type.isArrayType() || clazz.isArray() || type.isTypeOrSubTypeOf(Collection.class)) { |
| | | writer.assignNullSerializer(NullJsonSerializers.ARRAY_JSON_SERIALIZER); |
| | | } else if (type.isTypeOrSubTypeOf(OffsetDateTime.class)) { |
| | | writer.assignNullSerializer(NullJsonSerializers.STRING_JSON_SERIALIZER); |
| | | } else if (type.isTypeOrSubTypeOf(Date.class) || type.isTypeOrSubTypeOf(TemporalAccessor.class)) { |
| | | writer.assignNullSerializer(NullJsonSerializers.STRING_JSON_SERIALIZER); |
| | | } else { |
| | | writer.assignNullSerializer(NullJsonSerializers.OBJECT_JSON_SERIALIZER); |
| | | } |
| | | }); |
| | | return super.changeProperties(config, beanDesc, beanProperties); |
| | | } |
| | | |
| | | public interface NullJsonSerializers { |
| | | |
| | | JsonSerializer<Object> STRING_JSON_SERIALIZER = new JsonSerializer<Object>() { |
| | | @Override |
| | | public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { |
| | | gen.writeString(StringPool.EMPTY); |
| | | } |
| | | }; |
| | | |
| | | JsonSerializer<Object> NUMBER_JSON_SERIALIZER = new JsonSerializer<Object>() { |
| | | @Override |
| | | public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { |
| | | gen.writeNumber(StringUtil.INDEX_NOT_FOUND); |
| | | } |
| | | }; |
| | | |
| | | JsonSerializer<Object> BOOLEAN_JSON_SERIALIZER = new JsonSerializer<Object>() { |
| | | @Override |
| | | public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { |
| | | gen.writeObject(Boolean.FALSE); |
| | | } |
| | | }; |
| | | |
| | | JsonSerializer<Object> ARRAY_JSON_SERIALIZER = new JsonSerializer<Object>() { |
| | | @Override |
| | | public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { |
| | | gen.writeStartArray(); |
| | | gen.writeEndArray(); |
| | | } |
| | | }; |
| | | |
| | | JsonSerializer<Object> OBJECT_JSON_SERIALIZER = new JsonSerializer<Object>() { |
| | | @Override |
| | | public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { |
| | | gen.writeStartObject(); |
| | | gen.writeEndObject(); |
| | | } |
| | | }; |
| | | |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.jackson; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | /** |
| | | * jackson é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @ConfigurationProperties("blade.jackson") |
| | | public class BladeJacksonProperties { |
| | | |
| | | /** |
| | | * null 转为 空ï¼å符串转æ""ï¼æ°ç»è½¬ä¸º[]ï¼å¯¹è±¡è½¬ä¸º{}ï¼æ°å转为-1 |
| | | */ |
| | | private Boolean nullToEmpty = Boolean.TRUE; |
| | | /** |
| | | * ååºå°å端ï¼å¤§æ°å¼èªå¨ååºä¸º Stringï¼é¿å
精度丢失 |
| | | */ |
| | | private Boolean bigNumToString = Boolean.TRUE; |
| | | /** |
| | | * æ¯æ MediaType text/plainï¼ç¨äºå blade-api-crypto ä¸èµ·ä½¿ç¨ |
| | | */ |
| | | private Boolean supportTextPlain = Boolean.FALSE; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.jackson; |
| | | |
| | | import com.fasterxml.jackson.databind.module.SimpleModule; |
| | | import com.fasterxml.jackson.datatype.jsr310.PackageVersion; |
| | | import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; |
| | | import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; |
| | | import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; |
| | | import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; |
| | | import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; |
| | | import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; |
| | | import org.springblade.core.tool.utils.DateTimeUtil; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | |
| | | /** |
| | | * java 8 æ¶é´é»è®¤åºåå |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeJavaTimeModule extends SimpleModule { |
| | | public static final BladeJavaTimeModule INSTANCE = new BladeJavaTimeModule(); |
| | | |
| | | public BladeJavaTimeModule() { |
| | | super(PackageVersion.VERSION); |
| | | this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeUtil.DATETIME_FORMAT)); |
| | | this.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeUtil.DATE_FORMAT)); |
| | | this.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeUtil.TIME_FORMAT)); |
| | | this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeUtil.DATETIME_FORMAT)); |
| | | this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeUtil.DATE_FORMAT)); |
| | | this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeUtil.TIME_FORMAT)); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.jackson; |
| | | |
| | | import com.fasterxml.jackson.databind.module.SimpleModule; |
| | | import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.BigInteger; |
| | | |
| | | /** |
| | | * å¤§æ´æ°åºåå为 String å符串ï¼é¿å
æµè§å¨ä¸¢å¤±ç²¾åº¦ |
| | | * |
| | | * <p> |
| | | * å端建议éç¨ï¼ |
| | | * bignumber åºï¼ https://github.com/MikeMcl/bignumber.js |
| | | * decimal.js åºï¼ https://github.com/MikeMcl/decimal.js |
| | | * </p> |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeNumberModule extends SimpleModule { |
| | | public static final BladeNumberModule INSTANCE = new BladeNumberModule(); |
| | | |
| | | public BladeNumberModule() { |
| | | super(BladeNumberModule.class.getName()); |
| | | // Long å BigInteger éç¨å®å¶çé»è¾åºååï¼é¿å
è¶
è¿jsç精度 |
| | | this.addSerializer(Long.class, BigNumberSerializer.instance); |
| | | this.addSerializer(Long.TYPE, BigNumberSerializer.instance); |
| | | this.addSerializer(BigInteger.class, BigNumberSerializer.instance); |
| | | // BigDecimal éç¨ toString é¿å
精度丢失ï¼å端éç¨ decimal.js æ¥è®¡ç®ã |
| | | this.addSerializer(BigDecimal.class, ToStringSerializer.instance); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.jackson; |
| | | |
| | | import com.fasterxml.jackson.core.JsonParser; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.core.TreeNode; |
| | | import com.fasterxml.jackson.core.json.JsonReadFeature; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.*; |
| | | import com.fasterxml.jackson.databind.type.CollectionLikeType; |
| | | import com.fasterxml.jackson.databind.type.MapType; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springblade.core.tool.utils.*; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.ZoneId; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * Jacksonå·¥å
·ç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Slf4j |
| | | public class JsonUtil { |
| | | |
| | | /** |
| | | * å°å¯¹è±¡åºååæjsonå符串 |
| | | * |
| | | * @param value javaBean |
| | | * @return jsonString jsonå符串 |
| | | */ |
| | | public static <T> String toJson(T value) { |
| | | try { |
| | | return getInstance().writeValueAsString(value); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * å°å¯¹è±¡åºååæ json byte æ°ç» |
| | | * |
| | | * @param object javaBean |
| | | * @return jsonString jsonå符串 |
| | | */ |
| | | public static byte[] toJsonAsBytes(Object object) { |
| | | try { |
| | | return getInstance().writeValueAsBytes(object); |
| | | } catch (JsonProcessingException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param content content |
| | | * @param valueType class |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | public static <T> T parse(String content, Class<T> valueType) { |
| | | try { |
| | | return getInstance().readValue(content, valueType); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param content content |
| | | * @param typeReference æ³åç±»å |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | public static <T> T parse(String content, TypeReference<T> typeReference) { |
| | | try { |
| | | return getInstance().readValue(content, typeReference); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°json byte æ°ç»ååºååæå¯¹è±¡ |
| | | * |
| | | * @param bytes json bytes |
| | | * @param valueType class |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | public static <T> T parse(byte[] bytes, Class<T> valueType) { |
| | | try { |
| | | return getInstance().readValue(bytes, valueType); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param bytes bytes |
| | | * @param typeReference æ³åç±»å |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | public static <T> T parse(byte[] bytes, TypeReference<T> typeReference) { |
| | | try { |
| | | return getInstance().readValue(bytes, typeReference); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param in InputStream |
| | | * @param valueType class |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | public static <T> T parse(InputStream in, Class<T> valueType) { |
| | | try { |
| | | return getInstance().readValue(in, valueType); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param in InputStream |
| | | * @param typeReference æ³åç±»å |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | public static <T> T parse(InputStream in, TypeReference<T> typeReference) { |
| | | try { |
| | | return getInstance().readValue(in, typeReference); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæList对象 |
| | | * |
| | | * @param content content |
| | | * @param valueTypeRef class |
| | | * @param <T> T æ³åæ è®° |
| | | * @return List<T> |
| | | */ |
| | | public static <T> List<T> parseArray(String content, Class<T> valueTypeRef) { |
| | | try { |
| | | |
| | | if (!StringUtil.startsWithIgnoreCase(content, StringPool.LEFT_SQ_BRACKET)) { |
| | | content = StringPool.LEFT_SQ_BRACKET + content + StringPool.RIGHT_SQ_BRACKET; |
| | | } |
| | | |
| | | List<Map<String, Object>> list = getInstance().readValue(content, new TypeReference<List<Map<String, Object>>>() { |
| | | }); |
| | | |
| | | List<T> result = new ArrayList<>(); |
| | | for (Map<String, Object> map : list) { |
| | | result.add(toPojo(map, valueTypeRef)); |
| | | } |
| | | return result; |
| | | } catch (IOException e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * å°jsonå符串转æ JsonNode |
| | | * |
| | | * @param jsonString jsonString |
| | | * @return jsonString jsonå符串 |
| | | */ |
| | | public static JsonNode readTree(String jsonString) { |
| | | Objects.requireNonNull(jsonString, "jsonString is null"); |
| | | try { |
| | | return getInstance().readTree(jsonString); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonå符串转æ JsonNode |
| | | * |
| | | * @param in InputStream |
| | | * @return jsonString jsonå符串 |
| | | */ |
| | | public static JsonNode readTree(InputStream in) { |
| | | Objects.requireNonNull(in, "InputStream in is null"); |
| | | try { |
| | | return getInstance().readTree(in); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonå符串转æ JsonNode |
| | | * |
| | | * @param content content |
| | | * @return jsonString jsonå符串 |
| | | */ |
| | | public static JsonNode readTree(byte[] content) { |
| | | Objects.requireNonNull(content, "byte[] content is null"); |
| | | try { |
| | | return getInstance().readTree(content); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonå符串转æ JsonNode |
| | | * |
| | | * @param jsonParser JsonParser |
| | | * @return jsonString jsonå符串 |
| | | */ |
| | | public static JsonNode readTree(JsonParser jsonParser) { |
| | | Objects.requireNonNull(jsonParser, "jsonParser is null"); |
| | | try { |
| | | return getInstance().readTree(jsonParser); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å°json byte æ°ç»ååºååæå¯¹è±¡ |
| | | * |
| | | * @param content json bytes |
| | | * @param valueType class |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | @Nullable |
| | | public static <T> T readValue(@Nullable byte[] content, Class<T> valueType) { |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, valueType); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param jsonString jsonString |
| | | * @param valueType class |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | @Nullable |
| | | public static <T> T readValue(@Nullable String jsonString, Class<T> valueType) { |
| | | if (StringUtil.isBlank(jsonString)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return getInstance().readValue(jsonString, valueType); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param in InputStream |
| | | * @param valueType class |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | @Nullable |
| | | public static <T> T readValue(@Nullable InputStream in, Class<T> valueType) { |
| | | if (in == null) { |
| | | return null; |
| | | } |
| | | try { |
| | | return getInstance().readValue(in, valueType); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param content bytes |
| | | * @param typeReference æ³åç±»å |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | @Nullable |
| | | public static <T> T readValue(@Nullable byte[] content, TypeReference<T> typeReference) { |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, typeReference); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param jsonString jsonString |
| | | * @param typeReference æ³åç±»å |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | @Nullable |
| | | public static <T> T readValue(@Nullable String jsonString, TypeReference<T> typeReference) { |
| | | if (StringUtil.isBlank(jsonString)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return getInstance().readValue(jsonString, typeReference); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°jsonååºååæå¯¹è±¡ |
| | | * |
| | | * @param in InputStream |
| | | * @param typeReference æ³åç±»å |
| | | * @param <T> T æ³åæ è®° |
| | | * @return Bean |
| | | */ |
| | | @Nullable |
| | | public static <T> T readValue(@Nullable InputStream in, TypeReference<T> typeReference) { |
| | | if (in == null) { |
| | | return null; |
| | | } |
| | | try { |
| | | return getInstance().readValue(in, typeReference); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°è£
map type |
| | | * |
| | | * @param keyClass key ç±»å |
| | | * @param valueClass value ç±»å |
| | | * @return MapType |
| | | */ |
| | | public static MapType getMapType(Class<?> keyClass, Class<?> valueClass) { |
| | | return getInstance().getTypeFactory().constructMapType(Map.class, keyClass, valueClass); |
| | | } |
| | | |
| | | /** |
| | | * å°è£
map type |
| | | * |
| | | * @param elementClass éåå¼ç±»å |
| | | * @return CollectionLikeType |
| | | */ |
| | | public static CollectionLikeType getListType(Class<?> elementClass) { |
| | | return getInstance().getTypeFactory().constructCollectionLikeType(List.class, elementClass); |
| | | } |
| | | |
| | | /** |
| | | * 读åéå |
| | | * |
| | | * @param content bytes |
| | | * @param elementClass elementClass |
| | | * @param <T> æ³å |
| | | * @return éå |
| | | */ |
| | | public static <T> List<T> readList(@Nullable byte[] content, Class<T> elementClass) { |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, getListType(elementClass)); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读åéå |
| | | * |
| | | * @param content InputStream |
| | | * @param elementClass elementClass |
| | | * @param <T> æ³å |
| | | * @return éå |
| | | */ |
| | | public static <T> List<T> readList(@Nullable InputStream content, Class<T> elementClass) { |
| | | if (content == null) { |
| | | return Collections.emptyList(); |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, getListType(elementClass)); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读åéå |
| | | * |
| | | * @param content bytes |
| | | * @param elementClass elementClass |
| | | * @param <T> æ³å |
| | | * @return éå |
| | | */ |
| | | public static <T> List<T> readList(@Nullable String content, Class<T> elementClass) { |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, getListType(elementClass)); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读åéå |
| | | * |
| | | * @param content bytes |
| | | * @param keyClass keyç±»å |
| | | * @param valueClass å¼ç±»å |
| | | * @param <K> æ³å |
| | | * @param <V> æ³å |
| | | * @return éå |
| | | */ |
| | | public static <K, V> Map<K, V> readMap(@Nullable byte[] content, Class<?> keyClass, Class<?> valueClass) { |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, getMapType(keyClass, valueClass)); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读åéå |
| | | * |
| | | * @param content InputStream |
| | | * @param keyClass keyç±»å |
| | | * @param valueClass å¼ç±»å |
| | | * @param <K> æ³å |
| | | * @param <V> æ³å |
| | | * @return éå |
| | | */ |
| | | public static <K, V> Map<K, V> readMap(@Nullable InputStream content, Class<?> keyClass, Class<?> valueClass) { |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, getMapType(keyClass, valueClass)); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读åéå |
| | | * |
| | | * @param content bytes |
| | | * @param keyClass keyç±»å |
| | | * @param valueClass å¼ç±»å |
| | | * @param <K> æ³å |
| | | * @param <V> æ³å |
| | | * @return éå |
| | | */ |
| | | public static <K, V> Map<K, V> readMap(@Nullable String content, Class<?> keyClass, Class<?> valueClass) { |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, getMapType(keyClass, valueClass)); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读åéå |
| | | * |
| | | * @param content bytes |
| | | * @return éå |
| | | */ |
| | | public static Map<String, Object> readMap(@Nullable String content) { |
| | | return readMap(content, String.class, Object.class); |
| | | } |
| | | |
| | | /** |
| | | * 读åéå |
| | | * |
| | | * @param content bytes |
| | | * @return éå |
| | | */ |
| | | public static List<Map<String, Object>> readListMap(@Nullable String content) { |
| | | if (ObjectUtil.isEmpty(content)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | try { |
| | | return getInstance().readValue(content, new TypeReference<List<Map<String, Object>>>() { |
| | | }); |
| | | } catch (IOException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * jackson çç±»åè½¬æ¢ |
| | | * |
| | | * @param fromValue æ¥æºå¯¹è±¡ |
| | | * @param toValueType 转æ¢çç±»å |
| | | * @param <T> æ³åæ è®° |
| | | * @return 转æ¢ç»æ |
| | | */ |
| | | public static <T> T convertValue(Object fromValue, Class<T> toValueType) { |
| | | return getInstance().convertValue(fromValue, toValueType); |
| | | } |
| | | |
| | | /** |
| | | * jackson çç±»åè½¬æ¢ |
| | | * |
| | | * @param fromValue æ¥æºå¯¹è±¡ |
| | | * @param toValueType 转æ¢çç±»å |
| | | * @param <T> æ³åæ è®° |
| | | * @return 转æ¢ç»æ |
| | | */ |
| | | public static <T> T convertValue(Object fromValue, JavaType toValueType) { |
| | | return getInstance().convertValue(fromValue, toValueType); |
| | | } |
| | | |
| | | /** |
| | | * jackson çç±»åè½¬æ¢ |
| | | * |
| | | * @param fromValue æ¥æºå¯¹è±¡ |
| | | * @param toValueTypeRef æ³åç±»å |
| | | * @param <T> æ³åæ è®° |
| | | * @return 转æ¢ç»æ |
| | | */ |
| | | public static <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef) { |
| | | return getInstance().convertValue(fromValue, toValueTypeRef); |
| | | } |
| | | |
| | | /** |
| | | * tree 转对象 |
| | | * |
| | | * @param treeNode TreeNode |
| | | * @param valueType valueType |
| | | * @param <T> æ³åæ è®° |
| | | * @return 转æ¢ç»æ |
| | | */ |
| | | public static <T> T treeToValue(TreeNode treeNode, Class<T> valueType) { |
| | | try { |
| | | return getInstance().treeToValue(treeNode, valueType); |
| | | } catch (JsonProcessingException e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 对象转为 json node |
| | | * |
| | | * @param value 对象 |
| | | * @return JsonNode |
| | | */ |
| | | public static JsonNode valueToTree(@Nullable Object value) { |
| | | return getInstance().valueToTree(value); |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦å¯ä»¥åºåå |
| | | * |
| | | * @param value 对象 |
| | | * @return æ¯å¦å¯ä»¥åºåå |
| | | */ |
| | | public static boolean canSerialize(@Nullable Object value) { |
| | | if (value == null) { |
| | | return true; |
| | | } |
| | | return getInstance().canSerialize(value.getClass()); |
| | | } |
| | | |
| | | public static Map<String, Object> toMap(String content) { |
| | | try { |
| | | return getInstance().readValue(content, Map.class); |
| | | } catch (IOException e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static <T> Map<String, T> toMap(String content, Class<T> valueTypeRef) { |
| | | try { |
| | | Map<String, Map<String, Object>> map = getInstance().readValue(content, new TypeReference<Map<String, Map<String, Object>>>() { |
| | | }); |
| | | Map<String, T> result = new HashMap<>(16); |
| | | for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) { |
| | | result.put(entry.getKey(), toPojo(entry.getValue(), valueTypeRef)); |
| | | } |
| | | return result; |
| | | } catch (IOException e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static <T> T toPojo(Map fromValue, Class<T> toValueType) { |
| | | return getInstance().convertValue(fromValue, toValueType); |
| | | } |
| | | |
| | | public static ObjectMapper getInstance() { |
| | | return JacksonHolder.INSTANCE; |
| | | } |
| | | |
| | | private static class JacksonHolder { |
| | | private static final ObjectMapper INSTANCE = new JacksonObjectMapper(); |
| | | } |
| | | |
| | | private static class JacksonObjectMapper extends ObjectMapper { |
| | | private static final long serialVersionUID = 4288193147502386170L; |
| | | |
| | | private static final Locale CHINA = Locale.CHINA; |
| | | |
| | | public JacksonObjectMapper(ObjectMapper src) { |
| | | super(src); |
| | | } |
| | | |
| | | public JacksonObjectMapper() { |
| | | super(); |
| | | //设置å°ç¹ä¸ºä¸å½ |
| | | super.setLocale(CHINA); |
| | | //廿é»è®¤çæ¶é´æ³æ ¼å¼ |
| | | super.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); |
| | | //设置为ä¸å½ä¸æµ·æ¶åº |
| | | super.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault())); |
| | | //åºååæ¶ï¼æ¥æçç»ä¸æ ¼å¼ |
| | | super.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_DATETIME, Locale.CHINA)); |
| | | // åå¼å· |
| | | super.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); |
| | | // å
许JSONå符串å
å«éå¼å·æ§å¶å符ï¼å¼å°äº32çASCIIå符ï¼å
å«å¶è¡¨ç¬¦åæ¢è¡ç¬¦ï¼ |
| | | super.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true); |
| | | super.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true); |
| | | super.findAndRegisterModules(); |
| | | //失败å¤ç |
| | | super.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); |
| | | super.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
| | | //åå¼å·å¤ç |
| | | super.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature(), true); |
| | | //ååºååæ¶ï¼å±æ§ä¸åå¨çå
¼å®¹å¤çs |
| | | super.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); |
| | | //æ¥ææ ¼å¼å |
| | | super.registerModule(new BladeJavaTimeModule()); |
| | | super.findAndRegisterModules(); |
| | | } |
| | | |
| | | @Override |
| | | public ObjectMapper copy() { |
| | | return new JacksonObjectMapper(this); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.jackson; |
| | | |
| | | import com.fasterxml.jackson.core.JsonGenerator; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import org.springblade.core.tool.utils.Charsets; |
| | | import org.springframework.http.HttpOutputMessage; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.http.converter.HttpMessageNotWritableException; |
| | | import org.springframework.lang.NonNull; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.util.StreamUtils; |
| | | |
| | | import java.io.IOException; |
| | | import java.lang.reflect.Type; |
| | | import java.nio.charset.Charset; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * é对 api æå¡å¯¹ android å ios å¤çç å读åç jackson å¤ç |
| | | * |
| | | * <p> |
| | | * 1. app ç«¯ä¸æ¥æ°æ®æ¯ ä½¿ç¨ readObjectMapper |
| | | * 2. è¿åç» app ç«¯çæ°æ®ä½¿ç¨ writeObjectMapper |
| | | * 3. 妿æ¯è¿åå符串ï¼ç´æ¥ç¸åºï¼ä¸å json å¤ç |
| | | * </p> |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class MappingApiJackson2HttpMessageConverter extends AbstractReadWriteJackson2HttpMessageConverter { |
| | | |
| | | @Nullable |
| | | private String jsonPrefix; |
| | | |
| | | public MappingApiJackson2HttpMessageConverter(ObjectMapper objectMapper, BladeJacksonProperties properties) { |
| | | super(objectMapper, initWriteObjectMapper(objectMapper, properties), initMediaType(properties)); |
| | | } |
| | | |
| | | private static List<MediaType> initMediaType(BladeJacksonProperties properties) { |
| | | List<MediaType> supportedMediaTypes = new ArrayList<>(); |
| | | supportedMediaTypes.add(MediaType.APPLICATION_JSON); |
| | | supportedMediaTypes.add(new MediaType("application", "*+json")); |
| | | // æ¯æ text ææ¬ï¼ç¨äºæ¥æç¾å |
| | | if (Boolean.TRUE.equals(properties.getSupportTextPlain())) { |
| | | supportedMediaTypes.add(MediaType.TEXT_PLAIN); |
| | | } |
| | | return supportedMediaTypes; |
| | | } |
| | | |
| | | private static ObjectMapper initWriteObjectMapper(ObjectMapper readObjectMapper, BladeJacksonProperties properties) { |
| | | // æ·è´ readObjectMapper |
| | | ObjectMapper writeObjectMapper = readObjectMapper.copy(); |
| | | // 大æ°å 转 å符串 |
| | | if (Boolean.TRUE.equals(properties.getBigNumToString())) { |
| | | writeObjectMapper.registerModules(BladeNumberModule.INSTANCE); |
| | | } |
| | | // null å¤ç |
| | | if (Boolean.TRUE.equals(properties.getNullToEmpty())) { |
| | | writeObjectMapper.setSerializerFactory(writeObjectMapper.getSerializerFactory().withSerializerModifier(new BladeBeanSerializerModifier())); |
| | | writeObjectMapper.getSerializerProvider().setNullValueSerializer(BladeBeanSerializerModifier.NullJsonSerializers.STRING_JSON_SERIALIZER); |
| | | } |
| | | return writeObjectMapper; |
| | | } |
| | | |
| | | @Override |
| | | protected void writeInternal(@NonNull Object object, @Nullable Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { |
| | | // 妿æ¯å符串ï¼ç´æ¥ååº |
| | | if (object instanceof String) { |
| | | Charset defaultCharset = this.getDefaultCharset(); |
| | | Charset charset = defaultCharset == null ? Charsets.UTF_8 : defaultCharset; |
| | | StreamUtils.copy((String) object, charset, outputMessage.getBody()); |
| | | } else { |
| | | super.writeInternal(object, type, outputMessage); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Specify a custom prefix to use for this view's JSON output. |
| | | * Default is none. |
| | | * |
| | | * @param jsonPrefix jsonPrefix |
| | | * @see #setPrefixJson |
| | | */ |
| | | public void setJsonPrefix(@Nullable String jsonPrefix) { |
| | | this.jsonPrefix = jsonPrefix; |
| | | } |
| | | |
| | | /** |
| | | * Indicate whether the JSON output by this view should be prefixed with ")]}', ". Default is false. |
| | | * <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. |
| | | * The prefix renders the string syntactically invalid as a script so that it cannot be hijacked. |
| | | * This prefix should be stripped before parsing the string as JSON. |
| | | * |
| | | * @param prefixJson prefixJson |
| | | * @see #setJsonPrefix |
| | | */ |
| | | public void setPrefixJson(boolean prefixJson) { |
| | | this.jsonPrefix = (prefixJson ? ")]}', " : null); |
| | | } |
| | | |
| | | @Override |
| | | protected void writePrefix(@NonNull JsonGenerator generator, @NonNull Object object) throws IOException { |
| | | if (this.jsonPrefix != null) { |
| | | generator.writeRaw(this.jsonPrefix); |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.node; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonInclude; |
| | | import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
| | | import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
| | | import lombok.Data; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * èç¹åºç±» |
| | | * |
| | | * @author smallchill |
| | | */ |
| | | @Data |
| | | public class BaseNode<T> implements INode<T> { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 主é®ID |
| | | */ |
| | | @JsonSerialize(using = ToStringSerializer.class) |
| | | protected Long id; |
| | | |
| | | /** |
| | | * ç¶èç¹ID |
| | | */ |
| | | @JsonSerialize(using = ToStringSerializer.class) |
| | | protected Long parentId; |
| | | |
| | | /** |
| | | * ååèç¹ |
| | | */ |
| | | @JsonInclude(JsonInclude.Include.NON_EMPTY) |
| | | protected List<T> children = new ArrayList<T>(); |
| | | |
| | | /** |
| | | * æ¯å¦æååèç¹ |
| | | */ |
| | | @JsonInclude(JsonInclude.Include.NON_EMPTY) |
| | | private Boolean hasChildren; |
| | | |
| | | /** |
| | | * æ¯å¦æååèç¹ |
| | | * |
| | | * @return Boolean |
| | | */ |
| | | @Override |
| | | public Boolean getHasChildren() { |
| | | if (children.size() > 0) { |
| | | return true; |
| | | } else { |
| | | return this.hasChildren; |
| | | } |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.node; |
| | | |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | |
| | | /** |
| | | * 森æèç¹ç±» |
| | | * |
| | | * @author smallchill |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | public class ForestNode extends BaseNode<ForestNode> { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * èç¹å
容 |
| | | */ |
| | | private Object content; |
| | | |
| | | public ForestNode(Long id, Long parentId, Object content) { |
| | | this.id = id; |
| | | this.parentId = parentId; |
| | | this.content = content; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.node; |
| | | |
| | | import com.google.common.collect.ImmutableMap; |
| | | import com.google.common.collect.Maps; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 森æç®¡çç±» |
| | | * |
| | | * @author smallchill |
| | | */ |
| | | public class ForestNodeManager<T extends INode<T>> { |
| | | |
| | | /** |
| | | * 森æçææèç¹ |
| | | */ |
| | | private final ImmutableMap<Long, T> nodeMap; |
| | | |
| | | /** |
| | | * 森æçç¶èç¹ID |
| | | */ |
| | | private final Map<Long, Object> parentIdMap = Maps.newHashMap(); |
| | | |
| | | public ForestNodeManager(List<T> nodes) { |
| | | nodeMap = Maps.uniqueIndex(nodes, INode::getId); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®èç¹IDè·åä¸ä¸ªèç¹ |
| | | * |
| | | * @param id èç¹ID |
| | | * @return 对åºçèç¹å¯¹è±¡ |
| | | */ |
| | | public INode<T> getTreeNodeAt(Long id) { |
| | | if (nodeMap.containsKey(id)) { |
| | | return nodeMap.get(id); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * å¢å ç¶èç¹ID |
| | | * |
| | | * @param parentId ç¶èç¹ID |
| | | */ |
| | | public void addParentId(Long parentId) { |
| | | parentIdMap.put(parentId, StringPool.EMPTY); |
| | | } |
| | | |
| | | /** |
| | | * è·åæ çæ ¹èç¹(ä¸ä¸ªæ£®æå¯¹åºå¤é¢æ ) |
| | | * |
| | | * @return æ çæ ¹èç¹éå |
| | | */ |
| | | public List<T> getRoot() { |
| | | List<T> roots = new ArrayList<>(); |
| | | nodeMap.forEach((key, node) -> { |
| | | if (node.getParentId() == 0 || parentIdMap.containsKey(node.getId())) { |
| | | roots.add(node); |
| | | } |
| | | }); |
| | | return roots; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.node; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 森æèç¹å½å¹¶ç±» |
| | | * |
| | | * @author smallchill |
| | | */ |
| | | public class ForestNodeMerger { |
| | | |
| | | /** |
| | | * å°èç¹æ°ç»å½å¹¶ä¸ºä¸ä¸ªæ£®æï¼å¤æ£µæ ï¼ï¼å¡«å
èç¹çchildrenåï¼ |
| | | * æ¶é´å¤æåº¦ä¸ºO(n^2) |
| | | * |
| | | * @param items èç¹å |
| | | * @return 夿£µæ çæ ¹èç¹éå |
| | | */ |
| | | public static <T extends INode<T>> List<T> merge(List<T> items) { |
| | | ForestNodeManager<T> forestNodeManager = new ForestNodeManager<>(items); |
| | | items.forEach(forestNode -> { |
| | | if (forestNode.getParentId() != 0) { |
| | | INode<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId()); |
| | | if (node != null) { |
| | | node.getChildren().add(forestNode); |
| | | } else { |
| | | forestNodeManager.addParentId(forestNode.getId()); |
| | | } |
| | | } |
| | | }); |
| | | return forestNodeManager.getRoot(); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.node; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Created by Blade. |
| | | * |
| | | * @author smallchill |
| | | */ |
| | | public interface INode<T> extends Serializable { |
| | | |
| | | /** |
| | | * ä¸»é® |
| | | * |
| | | * @return Long |
| | | */ |
| | | Long getId(); |
| | | |
| | | /** |
| | | * ç¶ä¸»é® |
| | | * |
| | | * @return Long |
| | | */ |
| | | Long getParentId(); |
| | | |
| | | /** |
| | | * ååèç¹ |
| | | * |
| | | * @return List<T> |
| | | */ |
| | | List<T> getChildren(); |
| | | |
| | | /** |
| | | * æ¯å¦æååèç¹ |
| | | * |
| | | * @return Boolean |
| | | */ |
| | | default Boolean getHasChildren() { |
| | | return false; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.node; |
| | | |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * Created by Blade. |
| | | * |
| | | * @author smallchill |
| | | */ |
| | | public class NodeTest { |
| | | |
| | | public static void main(String[] args) { |
| | | List<ForestNode> list = new ArrayList<>(); |
| | | list.add(new ForestNode(1L, 0L, "1")); |
| | | list.add(new ForestNode(2L, 0L, "2")); |
| | | list.add(new ForestNode(3L, 1L, "3")); |
| | | list.add(new ForestNode(4L, 2L, "4")); |
| | | list.add(new ForestNode(5L, 3L, "5")); |
| | | list.add(new ForestNode(6L, 4L, "6")); |
| | | list.add(new ForestNode(7L, 3L, "7")); |
| | | list.add(new ForestNode(8L, 5L, "8")); |
| | | list.add(new ForestNode(9L, 6L, "9")); |
| | | list.add(new ForestNode(10L, 9L, "10")); |
| | | List<ForestNode> tns = ForestNodeMerger.merge(list); |
| | | tns.forEach(node -> |
| | | System.out.println(JsonUtil.toJson(node)) |
| | | ); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.node; |
| | | |
| | | import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
| | | import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
| | | import lombok.Data; |
| | | import org.springblade.core.tool.utils.Func; |
| | | |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * æ åèç¹ç±» |
| | | * |
| | | * @author smallchill |
| | | */ |
| | | @Data |
| | | public class TreeNode extends BaseNode<TreeNode> { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private String title; |
| | | |
| | | @JsonSerialize(using = ToStringSerializer.class) |
| | | private Long key; |
| | | |
| | | @JsonSerialize(using = ToStringSerializer.class) |
| | | private Long value; |
| | | |
| | | @Override |
| | | public boolean equals(Object obj) { |
| | | if (this == obj) { |
| | | return true; |
| | | } |
| | | if (obj == null) { |
| | | return false; |
| | | } |
| | | TreeNode other = (TreeNode) obj; |
| | | return Func.equals(this.getId(), other.getId()); |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return Objects.hash(id, parentId); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.spel; |
| | | |
| | | import org.springframework.aop.support.AopUtils; |
| | | import org.springframework.beans.factory.BeanFactory; |
| | | import org.springframework.context.expression.AnnotatedElementKey; |
| | | import org.springframework.context.expression.BeanFactoryResolver; |
| | | import org.springframework.context.expression.CachedExpressionEvaluator; |
| | | import org.springframework.context.expression.MethodBasedEvaluationContext; |
| | | import org.springframework.expression.EvaluationContext; |
| | | import org.springframework.expression.Expression; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * ç¼å spEl æé«æ§è½ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BladeExpressionEvaluator extends CachedExpressionEvaluator { |
| | | private final Map<ExpressionKey, Expression> expressionCache = new ConcurrentHashMap<>(64); |
| | | private final Map<AnnotatedElementKey, Method> methodCache = new ConcurrentHashMap<>(64); |
| | | |
| | | /** |
| | | * Create an {@link EvaluationContext}. |
| | | * |
| | | * @param method the method |
| | | * @param args the method arguments |
| | | * @param target the target object |
| | | * @param targetClass the target class |
| | | * @return the evaluation context |
| | | */ |
| | | public EvaluationContext createContext(Method method, Object[] args, Object target, Class<?> targetClass, @Nullable BeanFactory beanFactory) { |
| | | Method targetMethod = getTargetMethod(targetClass, method); |
| | | BladeExpressionRootObject rootObject = new BladeExpressionRootObject(method, args, target, targetClass, targetMethod); |
| | | MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(rootObject, targetMethod, args, getParameterNameDiscoverer()); |
| | | if (beanFactory != null) { |
| | | evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); |
| | | } |
| | | return evaluationContext; |
| | | } |
| | | |
| | | /** |
| | | * Create an {@link EvaluationContext}. |
| | | * |
| | | * @param method the method |
| | | * @param args the method arguments |
| | | * @param rootObject rootObject |
| | | * @param targetClass the target class |
| | | * @return the evaluation context |
| | | */ |
| | | public EvaluationContext createContext(Method method, Object[] args, Class<?> targetClass, Object rootObject, @Nullable BeanFactory beanFactory) { |
| | | Method targetMethod = getTargetMethod(targetClass, method); |
| | | MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(rootObject, targetMethod, args, getParameterNameDiscoverer()); |
| | | if (beanFactory != null) { |
| | | evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); |
| | | } |
| | | return evaluationContext; |
| | | } |
| | | |
| | | @Nullable |
| | | public Object eval(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) { |
| | | return eval(expression, methodKey, evalContext, null); |
| | | } |
| | | |
| | | @Nullable |
| | | public <T> T eval(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext, @Nullable Class<T> valueType) { |
| | | return getExpression(this.expressionCache, methodKey, expression).getValue(evalContext, valueType); |
| | | } |
| | | |
| | | @Nullable |
| | | public String evalAsText(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) { |
| | | return eval(expression, methodKey, evalContext, String.class); |
| | | } |
| | | |
| | | public boolean evalAsBool(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) { |
| | | return Boolean.TRUE.equals(eval(expression, methodKey, evalContext, Boolean.class)); |
| | | } |
| | | |
| | | private Method getTargetMethod(Class<?> targetClass, Method method) { |
| | | AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass); |
| | | return methodCache.computeIfAbsent(methodKey, (key) -> AopUtils.getMostSpecificMethod(method, targetClass)); |
| | | } |
| | | |
| | | /** |
| | | * Clear all caches. |
| | | */ |
| | | public void clear() { |
| | | this.expressionCache.clear(); |
| | | this.methodCache.clear(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.spel; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | import java.lang.reflect.Method; |
| | | |
| | | /** |
| | | * ExpressionRootObject |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public class BladeExpressionRootObject { |
| | | private final Method method; |
| | | |
| | | private final Object[] args; |
| | | |
| | | private final Object target; |
| | | |
| | | private final Class<?> targetClass; |
| | | |
| | | private final Method targetMethod; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.ssl; |
| | | |
| | | import javax.net.ssl.X509TrustManager; |
| | | import java.security.cert.CertificateException; |
| | | import java.security.cert.X509Certificate; |
| | | |
| | | /** |
| | | * ä¸è¿è¡è¯ä¹¦æ ¡éª |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class DisableValidationTrustManager implements X509TrustManager { |
| | | |
| | | public static final X509TrustManager INSTANCE = new DisableValidationTrustManager(); |
| | | |
| | | @Override |
| | | public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { |
| | | } |
| | | |
| | | @Override |
| | | public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { |
| | | } |
| | | |
| | | @Override |
| | | public X509Certificate[] getAcceptedIssuers() { |
| | | return new X509Certificate[0]; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.ssl; |
| | | |
| | | import javax.net.ssl.HostnameVerifier; |
| | | import javax.net.ssl.SSLSession; |
| | | |
| | | /** |
| | | * ä¿¡ä»»ææ host name |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class TrustAllHostNames implements HostnameVerifier { |
| | | public static final TrustAllHostNames INSTANCE = new TrustAllHostNames(); |
| | | |
| | | @Override |
| | | public boolean verify(String s, SSLSession sslSession) { |
| | | return true; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.support; |
| | | |
| | | import lombok.Getter; |
| | | import lombok.ToString; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * è·è¸ªç±»å卿¯è¾ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Getter |
| | | @ToString |
| | | public class BeanDiff { |
| | | /** |
| | | * åæ´åæ®µ |
| | | */ |
| | | private final Set<String> fields = new HashSet<>(); |
| | | /** |
| | | * æ§å¼ |
| | | */ |
| | | private final Map<String, Object> oldValues = new HashMap<>(); |
| | | /** |
| | | * æ°å¼ |
| | | */ |
| | | private final Map<String, Object> newValues = new HashMap<>(); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.support; |
| | | |
| | | import java.util.function.Supplier; |
| | | |
| | | /** |
| | | * è§£å³ no binder available é®é¢ |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class BinderSupplier implements Supplier<Object> { |
| | | |
| | | @Override |
| | | public Object get() { |
| | | return null; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.support; |
| | | |
| | | /** |
| | | * Created by Blade. |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class CoreMain { |
| | | |
| | | public static void main(String[] args) { |
| | | System.out.println("init core module"); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.support; |
| | | |
| | | |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.Writer; |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * FastStringWriterï¼æ´æ¹äº jdk CharArrayWriter |
| | | * |
| | | * <p> |
| | | * 1. 廿äºé |
| | | * 2. åå§å®¹éç± 32 æ¹ä¸º 64 |
| | | * </p> |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class FastStringWriter extends Writer { |
| | | /** |
| | | * The buffer where data is stored. |
| | | */ |
| | | private char[] buf; |
| | | /** |
| | | * The number of chars in the buffer. |
| | | */ |
| | | private int count; |
| | | |
| | | /** |
| | | * Creates a new CharArrayWriter. |
| | | */ |
| | | public FastStringWriter() { |
| | | this(64); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new CharArrayWriter with the specified initial size. |
| | | * |
| | | * @param initialSize an int specifying the initial buffer size. |
| | | * @throws IllegalArgumentException if initialSize is negative |
| | | */ |
| | | public FastStringWriter(int initialSize) { |
| | | if (initialSize < 0) { |
| | | throw new IllegalArgumentException("Negative initial size: " + initialSize); |
| | | } |
| | | buf = new char[initialSize]; |
| | | } |
| | | |
| | | /** |
| | | * Writes a character to the buffer. |
| | | */ |
| | | @Override |
| | | public void write(int c) { |
| | | int newCount = count + 1; |
| | | if (newCount > buf.length) { |
| | | buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newCount)); |
| | | } |
| | | buf[count] = (char) c; |
| | | count = newCount; |
| | | } |
| | | |
| | | /** |
| | | * Writes characters to the buffer. |
| | | * |
| | | * @param c the data to be written |
| | | * @param off the start offset in the data |
| | | * @param len the number of chars that are written |
| | | */ |
| | | @Override |
| | | public void write(char[] c, int off, int len) { |
| | | if ((off < 0) || (off > c.length) || (len < 0) || |
| | | ((off + len) > c.length) || ((off + len) < 0)) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } else if (len == 0) { |
| | | return; |
| | | } |
| | | int newCount = count + len; |
| | | if (newCount > buf.length) { |
| | | buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newCount)); |
| | | } |
| | | System.arraycopy(c, off, buf, count, len); |
| | | count = newCount; |
| | | } |
| | | |
| | | /** |
| | | * Write a portion of a string to the buffer. |
| | | * |
| | | * @param str String to be written from |
| | | * @param off Offset from which to start reading characters |
| | | * @param len Number of characters to be written |
| | | */ |
| | | @Override |
| | | public void write(String str, int off, int len) { |
| | | int newCount = count + len; |
| | | if (newCount > buf.length) { |
| | | buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newCount)); |
| | | } |
| | | str.getChars(off, off + len, buf, count); |
| | | count = newCount; |
| | | } |
| | | |
| | | /** |
| | | * Writes the contents of the buffer to another character stream. |
| | | * |
| | | * @param out the output stream to write to |
| | | * @throws IOException If an I/O error occurs. |
| | | */ |
| | | public void writeTo(Writer out) throws IOException { |
| | | out.write(buf, 0, count); |
| | | } |
| | | |
| | | /** |
| | | * Appends the specified character sequence to this writer. |
| | | * |
| | | * <p> An invocation of this method of the form <tt>out.append(csq)</tt> |
| | | * behaves in exactly the same way as the invocation |
| | | * |
| | | * <pre> |
| | | * out.write(csq.toString()) </pre> |
| | | * |
| | | * <p> Depending on the specification of <tt>toString</tt> for the |
| | | * character sequence <tt>csq</tt>, the entire sequence may not be |
| | | * appended. For instance, invoking the <tt>toString</tt> method of a |
| | | * character buffer will return a subsequence whose content depends upon |
| | | * the buffer's position and limit. |
| | | * |
| | | * @param csq The character sequence to append. If <tt>csq</tt> is |
| | | * <tt>null</tt>, then the four characters <tt>"null"</tt> are |
| | | * appended to this writer. |
| | | * @return This writer |
| | | */ |
| | | @Override |
| | | public FastStringWriter append(CharSequence csq) { |
| | | String s = (csq == null ? StringPool.NULL : csq.toString()); |
| | | write(s, 0, s.length()); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Appends a subsequence of the specified character sequence to this writer. |
| | | * |
| | | * <p> An invocation of this method of the form <tt>out.append(csq, start, |
| | | * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in |
| | | * exactly the same way as the invocation |
| | | * |
| | | * <pre> |
| | | * out.write(csq.subSequence(start, end).toString()) </pre> |
| | | * |
| | | * @param csq The character sequence from which a subsequence will be |
| | | * appended. If <tt>csq</tt> is <tt>null</tt>, then characters |
| | | * will be appended as if <tt>csq</tt> contained the four |
| | | * characters <tt>"null"</tt>. |
| | | * @param start The index of the first character in the subsequence |
| | | * @param end The index of the character following the last character in the |
| | | * subsequence |
| | | * @return This writer |
| | | * @throws IndexOutOfBoundsException If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt> |
| | | * is greater than <tt>end</tt>, or <tt>end</tt> is greater than |
| | | * <tt>csq.length()</tt> |
| | | */ |
| | | @Override |
| | | public FastStringWriter append(CharSequence csq, int start, int end) { |
| | | String s = (csq == null ? StringPool.NULL : csq).subSequence(start, end).toString(); |
| | | write(s, 0, s.length()); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Appends the specified character to this writer. |
| | | * |
| | | * <p> An invocation of this method of the form <tt>out.append(c)</tt> |
| | | * behaves in exactly the same way as the invocation |
| | | * |
| | | * <pre> |
| | | * out.write(c) </pre> |
| | | * |
| | | * @param c The 16-bit character to append |
| | | * @return This writer |
| | | */ |
| | | @Override |
| | | public FastStringWriter append(char c) { |
| | | write(c); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Resets the buffer so that you can use it again without |
| | | * throwing away the already allocated buffer. |
| | | */ |
| | | public void reset() { |
| | | count = 0; |
| | | } |
| | | |
| | | /** |
| | | * Returns a copy of the input data. |
| | | * |
| | | * @return an array of chars copied from the input data. |
| | | */ |
| | | public char[] toCharArray() { |
| | | return Arrays.copyOf(buf, count); |
| | | } |
| | | |
| | | /** |
| | | * Returns the current size of the buffer. |
| | | * |
| | | * @return an int representing the current size of the buffer. |
| | | */ |
| | | public int size() { |
| | | return count; |
| | | } |
| | | |
| | | /** |
| | | * Converts input data to a string. |
| | | * |
| | | * @return the string. |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return new String(buf, 0, count); |
| | | } |
| | | |
| | | /** |
| | | * Flush the stream. |
| | | */ |
| | | @Override |
| | | public void flush() { |
| | | } |
| | | |
| | | /** |
| | | * Close the stream. This method does not release the buffer, since its |
| | | * contents might still be required. Note: Invoking this method in this class |
| | | * will have no effect. |
| | | */ |
| | | @Override |
| | | public void close() { |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.support; |
| | | |
| | | import java.io.OutputStream; |
| | | |
| | | /** |
| | | * A factory for creating MultiOutputStream objects. |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public interface IMultiOutputStream { |
| | | |
| | | /** |
| | | * Builds the output stream. |
| | | * |
| | | * @param params the params |
| | | * @return the output stream |
| | | */ |
| | | OutputStream buildOutputStream(Integer... params); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.support; |
| | | |
| | | /** |
| | | * å¾çæä½ç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class ImagePosition { |
| | | |
| | | /** |
| | | * å¾çé¡¶é¨. |
| | | */ |
| | | public static final int TOP = 32; |
| | | |
| | | /** |
| | | * å¾çä¸é¨. |
| | | */ |
| | | public static final int MIDDLE = 16; |
| | | |
| | | /** |
| | | * å¾çåºé¨. |
| | | */ |
| | | public static final int BOTTOM = 8; |
| | | |
| | | /** |
| | | * å¾ç左侧. |
| | | */ |
| | | public static final int LEFT = 4; |
| | | |
| | | /** |
| | | * å¾çå±
ä¸. |
| | | */ |
| | | public static final int CENTER = 2; |
| | | |
| | | /** |
| | | * å¾çå³ä¾§. |
| | | */ |
| | | public static final int RIGHT = 1; |
| | | |
| | | /** |
| | | * 横åè¾¹è·ï¼é å·¦æé 峿¶åè¾¹ççè·ç¦». |
| | | */ |
| | | private static final int PADDING_HORI = 6; |
| | | |
| | | /** |
| | | * 纵åè¾¹è·ï¼é 䏿é åºæ¶åè¾¹ççè·ç¦». |
| | | */ |
| | | private static final int PADDING_VERT = 6; |
| | | |
| | | |
| | | /** |
| | | * å¾çä¸ç[å·¦ä¸è§]çxåæ . |
| | | */ |
| | | private int boxPosX; |
| | | |
| | | /** |
| | | * å¾çä¸ç[å·¦ä¸è§]çyåæ . |
| | | */ |
| | | private int boxPosY; |
| | | |
| | | /** |
| | | * Instantiates a new image position. |
| | | * |
| | | * @param width the width |
| | | * @param height the height |
| | | * @param boxWidth the box width |
| | | * @param boxHeight the box height |
| | | * @param style the style |
| | | */ |
| | | public ImagePosition(int width, int height, int boxWidth, int boxHeight, int style) { |
| | | switch (style & 7) { |
| | | case LEFT: |
| | | boxPosX = PADDING_HORI; |
| | | break; |
| | | case RIGHT: |
| | | boxPosX = width - boxWidth - PADDING_HORI; |
| | | break; |
| | | case CENTER: |
| | | default: |
| | | boxPosX = (width - boxWidth) / 2; |
| | | } |
| | | switch (style >> 3 << 3) { |
| | | case TOP: |
| | | boxPosY = PADDING_VERT; |
| | | break; |
| | | case MIDDLE: |
| | | boxPosY = (height - boxHeight) / 2; |
| | | break; |
| | | case BOTTOM: |
| | | default: |
| | | boxPosY = height - boxHeight - PADDING_VERT; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Gets the x. |
| | | * |
| | | * @return the x |
| | | */ |
| | | public int getX() { |
| | | return getX(0); |
| | | } |
| | | |
| | | /** |
| | | * Gets the x. |
| | | * |
| | | * @param x 横ååç§» |
| | | * @return the x |
| | | */ |
| | | public int getX(int x) { |
| | | return this.boxPosX + x; |
| | | } |
| | | |
| | | /** |
| | | * Gets the y. |
| | | * |
| | | * @return the y |
| | | */ |
| | | public int getY() { |
| | | return getY(0); |
| | | } |
| | | |
| | | /** |
| | | * Gets the y. |
| | | * |
| | | * @param y 纵ååç§» |
| | | * @return the y |
| | | */ |
| | | public int getY(int y) { |
| | | return this.boxPosY + y; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tool.support; |
| | | |
| | | import org.springblade.core.tool.utils.Func; |
| | | import org.springframework.util.LinkedCaseInsensitiveMap; |
| | | |
| | | import java.sql.Time; |
| | | import java.sql.Timestamp; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * é¾å¼map |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class Kv extends LinkedCaseInsensitiveMap<Object> { |
| | | |
| | | private Kv() { |
| | | super(); |
| | | } |
| | | |
| | | /** |
| | | * å建Kv |
| | | * |
| | | * @return Kv |
| | | */ |
| | | public static Kv create() { |
| | | return new Kv(); |
| | | } |
| | | |
| | | public static <K, V> HashMap<K, V> newMap() { |
| | | return new HashMap<>(16); |
| | | } |
| | | |
| | | /** |
| | | * 设置å |
| | | * |
| | | * @param attr 屿§ |
| | | * @param value å¼ |
| | | * @return æ¬èº« |
| | | */ |
| | | public Kv set(String attr, Object value) { |
| | | this.put(attr, value); |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置å
¨é¨ |
| | | * |
| | | * @param map 屿§ |
| | | * @return æ¬èº« |
| | | */ |
| | | public Kv setAll(Map<? extends String, ?> map) { |
| | | if (map != null) { |
| | | this.putAll(map); |
| | | } |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置åï¼å½é®æå¼ä¸ºnullæ¶å¿½ç¥ |
| | | * |
| | | * @param attr 屿§ |
| | | * @param value å¼ |
| | | * @return æ¬èº« |
| | | */ |
| | | public Kv setIgnoreNull(String attr, Object value) { |
| | | if (attr != null && value != null) { |
| | | set(attr, value); |
| | | } |
| | | return this; |
| | | } |
| | | |
| | | public Object getObj(String key) { |
| | | return super.get(key); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param <T> å¼ç±»å |
| | | * @param attr åæ®µå |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return åæ®µå¼ |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public <T> T get(String attr, T defaultValue) { |
| | | final Object result = get(attr); |
| | | return (T) (result != null ? result : defaultValue); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public String getStr(String attr) { |
| | | return Func.toStr(get(attr), null); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public Integer getInt(String attr) { |
| | | return Func.toInt(get(attr), -1); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public Long getLong(String attr) { |
| | | return Func.toLong(get(attr), -1L); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public Float getFloat(String attr) { |
| | | return Func.toFloat(get(attr), null); |
| | | } |
| | | |
| | | public Double getDouble(String attr) { |
| | | return Func.toDouble(get(attr), null); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public Boolean getBool(String attr) { |
| | | return Func.toBoolean(get(attr), null); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public byte[] getBytes(String attr) { |
| | | return get(attr, null); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public Date getDate(String attr) { |
| | | return get(attr, null); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public Time getTime(String attr) { |
| | | return get(attr, null); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public Timestamp getTimestamp(String attr) { |
| | | return get(attr, null); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ç¹å®ç±»åå¼ |
| | | * |
| | | * @param attr åæ®µå |
| | | * @return åæ®µå¼ |
| | | */ |
| | | public Number getNumber(String attr) { |
| | | return get(attr, null); |
| | | } |
| | | |
| | | @Override |
| | | public Kv clone() { |
| | | Kv clone = new Kv(); |
| | | clone.putAll(this); |
| | | return clone; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.support; |
| | | |
| | | import org.springblade.core.tool.utils.Func; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | /** |
| | | * å符串ååå¨ |
| | | * |
| | | * @author Looly |
| | | */ |
| | | public class StrSpliter { |
| | | |
| | | //---------------------------------------------------------------------------------------------- Split by char |
| | | |
| | | /** |
| | | * ååå符串路å¾ï¼ä»
æ¯æUnixåç符ï¼/ |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> splitPath(String str) { |
| | | return splitPath(str, 0); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串路å¾ï¼ä»
æ¯æUnixåç符ï¼/ |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static String[] splitPathToArray(String str) { |
| | | return toArray(splitPath(str)); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串路å¾ï¼ä»
æ¯æUnixåç符ï¼/ |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param limit éå¶åçæ° |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> splitPath(String str, int limit) { |
| | | return split(str, StringPool.SLASH, limit, true, true); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串路å¾ï¼ä»
æ¯æUnixåç符ï¼/ |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param limit éå¶åçæ° |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static String[] splitPathToArray(String str, int limit) { |
| | | return toArray(splitPath(str, limit)); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串 |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符 |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.2.1 |
| | | */ |
| | | public static List<String> splitTrim(String str, char separator, boolean ignoreEmpty) { |
| | | return split(str, separator, 0, true, ignoreEmpty); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串 |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符 |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> split(String str, char separator, boolean isTrim, boolean ignoreEmpty) { |
| | | return split(str, separator, 0, isTrim, ignoreEmpty); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串ï¼å¤§å°åææï¼å»é¤æ¯ä¸ªå
ç´ ä¸¤è¾¹ç©ºç½ç¬¦ |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符 |
| | | * @param limit éå¶åçæ°ï¼-1ä¸éå¶ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> splitTrim(String str, char separator, int limit, boolean ignoreEmpty) { |
| | | return split(str, separator, limit, true, ignoreEmpty, false); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串ï¼å¤§å°åææ |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符 |
| | | * @param limit éå¶åçæ°ï¼-1ä¸éå¶ |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> split(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { |
| | | return split(str, separator, limit, isTrim, ignoreEmpty, false); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串ï¼å¿½ç¥å¤§å°å |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符 |
| | | * @param limit éå¶åçæ°ï¼-1ä¸éå¶ |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.2.1 |
| | | */ |
| | | public static List<String> splitIgnoreCase(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { |
| | | return split(str, separator, limit, isTrim, ignoreEmpty, true); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串 |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符 |
| | | * @param limit éå¶åçæ°ï¼-1ä¸éå¶ |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @param ignoreCase æ¯å¦å¿½ç¥å¤§å°å |
| | | * @return åååçéå |
| | | * @since 3.2.1 |
| | | */ |
| | | public static List<String> split(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty, boolean ignoreCase) { |
| | | if (StringUtil.isEmpty(str)) { |
| | | return new ArrayList<String>(0); |
| | | } |
| | | if (limit == 1) { |
| | | return addToList(new ArrayList<String>(1), str, isTrim, ignoreEmpty); |
| | | } |
| | | |
| | | final ArrayList<String> list = new ArrayList<>(limit > 0 ? limit : 16); |
| | | int len = str.length(); |
| | | int start = 0; |
| | | for (int i = 0; i < len; i++) { |
| | | if (Func.equals(separator, str.charAt(i))) { |
| | | addToList(list, str.substring(start, i), isTrim, ignoreEmpty); |
| | | start = i + 1; |
| | | |
| | | //æ£æ¥æ¯å¦è¶
åºèå´ï¼æå¤§å
许limit-1个ï¼å©ä¸ä¸ä¸ªçç»æ«å°¾åç¬¦ä¸²ï¼ |
| | | if (limit > 0 && list.size() > limit - 2) { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | return addToList(list, str.substring(start, len), isTrim, ignoreEmpty); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串为å符串æ°ç» |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符 |
| | | * @param limit éå¶åçæ° |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static String[] splitToArray(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { |
| | | return toArray(split(str, separator, limit, isTrim, ignoreEmpty)); |
| | | } |
| | | |
| | | //---------------------------------------------------------------------------------------------- Split by String |
| | | |
| | | /** |
| | | * ååå符串ï¼ä¸å¿½ç¥å¤§å°å |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符串 |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> split(String str, String separator, boolean isTrim, boolean ignoreEmpty) { |
| | | return split(str, separator, -1, isTrim, ignoreEmpty, false); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串ï¼å»é¤æ¯ä¸ªå
ç´ ä¸¤è¾¹ç©ºæ ¼ï¼å¿½ç¥å¤§å°å |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符串 |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.2.1 |
| | | */ |
| | | public static List<String> splitTrim(String str, String separator, boolean ignoreEmpty) { |
| | | return split(str, separator, true, ignoreEmpty); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串ï¼ä¸å¿½ç¥å¤§å°å |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符串 |
| | | * @param limit éå¶åçæ° |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> split(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { |
| | | return split(str, separator, limit, isTrim, ignoreEmpty, false); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串ï¼å»é¤æ¯ä¸ªå
ç´ ä¸¤è¾¹ç©ºæ ¼ï¼å¿½ç¥å¤§å°å |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符串 |
| | | * @param limit éå¶åçæ° |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.2.1 |
| | | */ |
| | | public static List<String> splitTrim(String str, String separator, int limit, boolean ignoreEmpty) { |
| | | return split(str, separator, limit, true, ignoreEmpty); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串ï¼å¿½ç¥å¤§å°å |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符串 |
| | | * @param limit éå¶åçæ° |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.2.1 |
| | | */ |
| | | public static List<String> splitIgnoreCase(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { |
| | | return split(str, separator, limit, isTrim, ignoreEmpty, true); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串ï¼å»é¤æ¯ä¸ªå
ç´ ä¸¤è¾¹ç©ºæ ¼ï¼å¿½ç¥å¤§å°å |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符串 |
| | | * @param limit éå¶åçæ° |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.2.1 |
| | | */ |
| | | public static List<String> splitTrimIgnoreCase(String str, String separator, int limit, boolean ignoreEmpty) { |
| | | return split(str, separator, limit, true, ignoreEmpty, true); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串 |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符串 |
| | | * @param limit éå¶åçæ° |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @param ignoreCase æ¯å¦å¿½ç¥å¤§å°å |
| | | * @return åååçéå |
| | | * @since 3.2.1 |
| | | */ |
| | | public static List<String> split(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty, boolean ignoreCase) { |
| | | if (StringUtil.isEmpty(str)) { |
| | | return new ArrayList<String>(0); |
| | | } |
| | | if (limit == 1) { |
| | | return addToList(new ArrayList<String>(1), str, isTrim, ignoreEmpty); |
| | | } |
| | | |
| | | if (StringUtil.isEmpty(separator)) { |
| | | return split(str, limit); |
| | | } else if (separator.length() == 1) { |
| | | return split(str, separator.charAt(0), limit, isTrim, ignoreEmpty, ignoreCase); |
| | | } |
| | | |
| | | final ArrayList<String> list = new ArrayList<>(); |
| | | int len = str.length(); |
| | | int separatorLen = separator.length(); |
| | | int start = 0; |
| | | int i = 0; |
| | | while (i < len) { |
| | | i = StringUtil.indexOf(str, separator, start, ignoreCase); |
| | | if (i > -1) { |
| | | addToList(list, str.substring(start, i), isTrim, ignoreEmpty); |
| | | start = i + separatorLen; |
| | | |
| | | //æ£æ¥æ¯å¦è¶
åºèå´ï¼æå¤§å
许limit-1个ï¼å©ä¸ä¸ä¸ªçç»æ«å°¾åç¬¦ä¸²ï¼ |
| | | if (limit > 0 && list.size() > limit - 2) { |
| | | break; |
| | | } |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | return addToList(list, str.substring(start, len), isTrim, ignoreEmpty); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串为å符串æ°ç» |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符å符 |
| | | * @param limit éå¶åçæ° |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static String[] splitToArray(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { |
| | | return toArray(split(str, separator, limit, isTrim, ignoreEmpty)); |
| | | } |
| | | |
| | | //---------------------------------------------------------------------------------------------- Split by Whitespace |
| | | |
| | | /** |
| | | * 使ç¨ç©ºç½ç¬¦ååå符串<br> |
| | | * åååçå符串两边ä¸å
å«ç©ºç½ç¬¦ï¼ç©ºä¸²æç©ºç½ç¬¦ä¸²å¹¶ä¸å为å
ç´ ä¹ä¸ |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param limit éå¶åçæ° |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> split(String str, int limit) { |
| | | if (StringUtil.isEmpty(str)) { |
| | | return new ArrayList<String>(0); |
| | | } |
| | | if (limit == 1) { |
| | | return addToList(new ArrayList<String>(1), str, true, true); |
| | | } |
| | | |
| | | final ArrayList<String> list = new ArrayList<>(); |
| | | int len = str.length(); |
| | | int start = 0; |
| | | for (int i = 0; i < len; i++) { |
| | | if (Func.isEmpty(str.charAt(i))) { |
| | | addToList(list, str.substring(start, i), true, true); |
| | | start = i + 1; |
| | | if (limit > 0 && list.size() > limit - 2) { |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | return addToList(list, str.substring(start, len), true, true); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串为å符串æ°ç» |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param limit éå¶åçæ° |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static String[] splitToArray(String str, int limit) { |
| | | return toArray(split(str, limit)); |
| | | } |
| | | |
| | | //---------------------------------------------------------------------------------------------- Split by regex |
| | | |
| | | /** |
| | | * éè¿æ£åååå符串 |
| | | * |
| | | * @param str å符串 |
| | | * @param separatorPattern åé符æ£å{@link Pattern} |
| | | * @param limit éå¶åçæ° |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static List<String> split(String str, Pattern separatorPattern, int limit, boolean isTrim, boolean ignoreEmpty) { |
| | | if (StringUtil.isEmpty(str)) { |
| | | return new ArrayList<String>(0); |
| | | } |
| | | if (limit == 1) { |
| | | return addToList(new ArrayList<String>(1), str, isTrim, ignoreEmpty); |
| | | } |
| | | |
| | | if (null == separatorPattern) { |
| | | return split(str, limit); |
| | | } |
| | | |
| | | final Matcher matcher = separatorPattern.matcher(str); |
| | | final ArrayList<String> list = new ArrayList<>(); |
| | | int len = str.length(); |
| | | int start = 0; |
| | | while (matcher.find()) { |
| | | addToList(list, str.substring(start, matcher.start()), isTrim, ignoreEmpty); |
| | | start = matcher.end(); |
| | | |
| | | if (limit > 0 && list.size() > limit - 2) { |
| | | break; |
| | | } |
| | | } |
| | | return addToList(list, str.substring(start, len), isTrim, ignoreEmpty); |
| | | } |
| | | |
| | | /** |
| | | * éè¿æ£åååå符串为å符串æ°ç» |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separatorPattern åé符æ£å{@link Pattern} |
| | | * @param limit éå¶åçæ° |
| | | * @param isTrim æ¯å¦å»é¤åååç¬¦ä¸²åæ¯ä¸ªå
ç´ ä¸¤è¾¹çç©ºæ ¼ |
| | | * @param ignoreEmpty æ¯å¦å¿½ç¥ç©ºä¸² |
| | | * @return åååçéå |
| | | * @since 3.0.8 |
| | | */ |
| | | public static String[] splitToArray(String str, Pattern separatorPattern, int limit, boolean isTrim, boolean ignoreEmpty) { |
| | | return toArray(split(str, separatorPattern, limit, isTrim, ignoreEmpty)); |
| | | } |
| | | |
| | | //---------------------------------------------------------------------------------------------- Split by length |
| | | |
| | | /** |
| | | * æ ¹æ®ç»å®é¿åº¦ï¼å°ç»å®å符串æªå为å¤ä¸ªé¨å |
| | | * |
| | | * @param str å符串 |
| | | * @param len æ¯ä¸ä¸ªå°èçé¿åº¦ |
| | | * @return æªååçå符串æ°ç» |
| | | */ |
| | | public static String[] splitByLength(String str, int len) { |
| | | int partCount = str.length() / len; |
| | | int lastPartCount = str.length() % len; |
| | | int fixPart = 0; |
| | | if (lastPartCount != 0) { |
| | | fixPart = 1; |
| | | } |
| | | |
| | | final String[] strs = new String[partCount + fixPart]; |
| | | for (int i = 0; i < partCount + fixPart; i++) { |
| | | if (i == partCount + fixPart - 1 && lastPartCount != 0) { |
| | | strs[i] = str.substring(i * len, i * len + lastPartCount); |
| | | } else { |
| | | strs[i] = str.substring(i * len, i * len + len); |
| | | } |
| | | } |
| | | return strs; |
| | | } |
| | | |
| | | //---------------------------------------------------------------------------------------------------------- Private method start |
| | | |
| | | /** |
| | | * å°å符串å å
¥Listä¸ |
| | | * |
| | | * @param list å表 |
| | | * @param part 被å å
¥çé¨å |
| | | * @param isTrim æ¯å¦å»é¤ä¸¤ç«¯ç©ºç½ç¬¦ |
| | | * @param ignoreEmpty æ¯å¦ç¥è¿ç©ºå符串ï¼ç©ºå符串ä¸å为ä¸ä¸ªå
ç´ ï¼ |
| | | * @return å表 |
| | | */ |
| | | private static List<String> addToList(List<String> list, String part, boolean isTrim, boolean ignoreEmpty) { |
| | | part = part.toString(); |
| | | if (isTrim) { |
| | | part = part.trim(); |
| | | } |
| | | if (false == ignoreEmpty || false == part.isEmpty()) { |
| | | list.add(part); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * List转Array |
| | | * |
| | | * @param list List |
| | | * @return Array |
| | | */ |
| | | private static String[] toArray(List<String> list) { |
| | | return list.toArray(new String[list.size()]); |
| | | } |
| | | //---------------------------------------------------------------------------------------------------------- Private method end |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.support; |
| | | |
| | | import org.springblade.core.tool.utils.Exceptions; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.util.Objects; |
| | | import java.util.function.Consumer; |
| | | import java.util.function.Function; |
| | | import java.util.function.Supplier; |
| | | |
| | | /** |
| | | * Lambda 忣å¼å¸¸å¤ç |
| | | * https://segmentfault.com/a/1190000007832130 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class Try { |
| | | |
| | | public static <T, R> Function<T, R> of(UncheckedFunction<T, R> mapper) { |
| | | Objects.requireNonNull(mapper); |
| | | return t -> { |
| | | try { |
| | | return mapper.apply(t); |
| | | } catch (Exception e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | public static <T> Consumer<T> of(UncheckedConsumer<T> mapper) { |
| | | Objects.requireNonNull(mapper); |
| | | return t -> { |
| | | try { |
| | | mapper.accept(t); |
| | | } catch (Exception e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | public static <T> Supplier<T> of(UncheckedSupplier<T> mapper) { |
| | | Objects.requireNonNull(mapper); |
| | | return () -> { |
| | | try { |
| | | return mapper.get(); |
| | | } catch (Exception e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | @FunctionalInterface |
| | | public interface UncheckedFunction<T, R> { |
| | | /** |
| | | * apply |
| | | * |
| | | * @param t |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @Nullable |
| | | R apply(@Nullable T t) throws Exception; |
| | | } |
| | | |
| | | @FunctionalInterface |
| | | public interface UncheckedConsumer<T> { |
| | | /** |
| | | * accept |
| | | * |
| | | * @param t |
| | | * @throws Exception |
| | | */ |
| | | @Nullable |
| | | void accept(@Nullable T t) throws Exception; |
| | | } |
| | | |
| | | @FunctionalInterface |
| | | public interface UncheckedSupplier<T> { |
| | | /** |
| | | * get |
| | | * |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @Nullable |
| | | T get() throws Exception; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.tuple; |
| | | |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springblade.core.tool.utils.RsaUtil; |
| | | |
| | | import java.security.PrivateKey; |
| | | import java.security.PublicKey; |
| | | |
| | | /** |
| | | * rsa ç key pair å°è£
|
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @RequiredArgsConstructor |
| | | public class KeyPair { |
| | | private final java.security.KeyPair keyPair; |
| | | |
| | | public PublicKey getPublic() { |
| | | return keyPair.getPublic(); |
| | | } |
| | | |
| | | public PrivateKey getPrivate() { |
| | | return keyPair.getPrivate(); |
| | | } |
| | | |
| | | public byte[] getPublicBytes() { |
| | | return this.getPublic().getEncoded(); |
| | | } |
| | | |
| | | public byte[] getPrivateBytes() { |
| | | return this.getPrivate().getEncoded(); |
| | | } |
| | | |
| | | public String getPublicBase64() { |
| | | return RsaUtil.getKeyString(this.getPublic()); |
| | | } |
| | | |
| | | public String getPrivateBase64() { |
| | | return RsaUtil.getKeyString(this.getPrivate()); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "PublicKey=" + this.getPublicBase64() + '\n' + "PrivateKey=" + this.getPrivateBase64(); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.tuple; |
| | | |
| | | import lombok.*; |
| | | |
| | | /** |
| | | * tuple Pair |
| | | * |
| | | * @author L.cm |
| | | **/ |
| | | @Getter |
| | | @ToString |
| | | @EqualsAndHashCode |
| | | public class Pair<L, R> { |
| | | private static final Pair<Object, Object> EMPTY = new Pair<>(null, null); |
| | | |
| | | private final L left; |
| | | private final R right; |
| | | |
| | | /** |
| | | * Returns an empty pair. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <L, R> Pair<L, R> empty() { |
| | | return (Pair<L, R>) EMPTY; |
| | | } |
| | | |
| | | /** |
| | | * Constructs a pair with its left value being {@code left}, or returns an empty pair if |
| | | * {@code left} is null. |
| | | * |
| | | * @return the constructed pair or an empty pair if {@code left} is null. |
| | | */ |
| | | public static <L, R> Pair<L, R> createLeft(L left) { |
| | | if (left == null) { |
| | | return empty(); |
| | | } else { |
| | | return new Pair<>(left, null); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Constructs a pair with its right value being {@code right}, or returns an empty pair if |
| | | * {@code right} is null. |
| | | * |
| | | * @return the constructed pair or an empty pair if {@code right} is null. |
| | | */ |
| | | public static <L, R> Pair<L, R> createRight(R right) { |
| | | if (right == null) { |
| | | return empty(); |
| | | } else { |
| | | return new Pair<>(null, right); |
| | | } |
| | | } |
| | | |
| | | public static <L, R> Pair<L, R> create(L left, R right) { |
| | | if (right == null && left == null) { |
| | | return empty(); |
| | | } else { |
| | | return new Pair<>(left, right); |
| | | } |
| | | } |
| | | |
| | | private Pair(L left, R right) { |
| | | this.left = left; |
| | | this.right = right; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.util.Assert; |
| | | |
| | | import javax.crypto.Cipher; |
| | | import javax.crypto.spec.IvParameterSpec; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.nio.charset.Charset; |
| | | import java.util.Arrays; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * å®å
¨å
¼å®¹å¾®ä¿¡æä½¿ç¨çAESå å¯å·¥å
·ç±» |
| | | * aesçkeyå¿
é¡»æ¯256byteé¿ï¼æ¯å¦32个å符ï¼ï¼å¯ä»¥ä½¿ç¨AesKit.genAesKey()æ¥çæä¸ç»key |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class AesUtil { |
| | | |
| | | public static final Charset DEFAULT_CHARSET = Charsets.UTF_8; |
| | | |
| | | /** |
| | | * è·åå¯é¥ |
| | | * |
| | | * @return {String} |
| | | */ |
| | | public static String genAesKey() { |
| | | return StringUtil.random(32); |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] encrypt(String content, String aesTextKey) { |
| | | return encrypt(content.getBytes(DEFAULT_CHARSET), aesTextKey); |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param charset ç¼ç |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] encrypt(String content, Charset charset, String aesTextKey) { |
| | | return encrypt(content.getBytes(charset), aesTextKey); |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param content å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] encrypt(byte[] content, String aesTextKey) { |
| | | return encrypt(content, Objects.requireNonNull(aesTextKey).getBytes(DEFAULT_CHARSET)); |
| | | } |
| | | |
| | | /** |
| | | * hexå å¯ |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return {String} |
| | | */ |
| | | public static String encryptToHex(String content, String aesTextKey) { |
| | | return HexUtil.encodeToString(encrypt(content, aesTextKey)); |
| | | } |
| | | |
| | | /** |
| | | * hexå å¯ |
| | | * |
| | | * @param content å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return {String} |
| | | */ |
| | | public static String encryptToHex(byte[] content, String aesTextKey) { |
| | | return HexUtil.encodeToString(encrypt(content, aesTextKey)); |
| | | } |
| | | |
| | | /** |
| | | * Base64å å¯ |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return {String} |
| | | */ |
| | | public static String encryptToBase64(String content, String aesTextKey) { |
| | | return Base64Util.encodeToString(encrypt(content, aesTextKey)); |
| | | } |
| | | |
| | | /** |
| | | * Base64å å¯ |
| | | * |
| | | * @param content å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return {String} |
| | | */ |
| | | public static String encryptToBase64(byte[] content, String aesTextKey) { |
| | | return Base64Util.encodeToString(encrypt(content, aesTextKey)); |
| | | } |
| | | |
| | | /** |
| | | * hexè§£å¯ |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return {String} |
| | | */ |
| | | @Nullable |
| | | public static String decryptFormHexToString(@Nullable String content, String aesTextKey) { |
| | | byte[] hexBytes = decryptFormHex(content, aesTextKey); |
| | | if (hexBytes == null) { |
| | | return null; |
| | | } |
| | | return new String(hexBytes, DEFAULT_CHARSET); |
| | | } |
| | | |
| | | /** |
| | | * hexè§£å¯ |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | @Nullable |
| | | public static byte[] decryptFormHex(@Nullable String content, String aesTextKey) { |
| | | if (StringUtil.isBlank(content)) { |
| | | return null; |
| | | } |
| | | return decryptFormHex(content.getBytes(DEFAULT_CHARSET), aesTextKey); |
| | | } |
| | | |
| | | /** |
| | | * hexè§£å¯ |
| | | * |
| | | * @param content å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] decryptFormHex(byte[] content, String aesTextKey) { |
| | | return decrypt(HexUtil.decode(content), aesTextKey); |
| | | } |
| | | |
| | | /** |
| | | * Base64è§£å¯ |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return {String} |
| | | */ |
| | | @Nullable |
| | | public static String decryptFormBase64ToString(@Nullable String content, String aesTextKey) { |
| | | byte[] hexBytes = decryptFormBase64(content, aesTextKey); |
| | | if (hexBytes == null) { |
| | | return null; |
| | | } |
| | | return new String(hexBytes, DEFAULT_CHARSET); |
| | | } |
| | | |
| | | /** |
| | | * Base64è§£å¯ |
| | | * |
| | | * @param content ææ¬å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | @Nullable |
| | | public static byte[] decryptFormBase64(@Nullable String content, String aesTextKey) { |
| | | if (StringUtil.isBlank(content)) { |
| | | return null; |
| | | } |
| | | return decryptFormBase64(content.getBytes(DEFAULT_CHARSET), aesTextKey); |
| | | } |
| | | |
| | | /** |
| | | * Base64è§£å¯ |
| | | * |
| | | * @param content å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] decryptFormBase64(byte[] content, String aesTextKey) { |
| | | return decrypt(Base64Util.decode(content), aesTextKey); |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param content å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return {String} |
| | | */ |
| | | public static String decryptToString(byte[] content, String aesTextKey) { |
| | | return new String(decrypt(content, aesTextKey), DEFAULT_CHARSET); |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param content å
容 |
| | | * @param aesTextKey ææ¬å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] decrypt(byte[] content, String aesTextKey) { |
| | | return decrypt(content, Objects.requireNonNull(aesTextKey).getBytes(DEFAULT_CHARSET)); |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param content å
容 |
| | | * @param aesKey å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] encrypt(byte[] content, byte[] aesKey) { |
| | | return aes(Pkcs7Encoder.encode(content), aesKey, Cipher.ENCRYPT_MODE); |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param encrypted å
容 |
| | | * @param aesKey å¯é¥ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] decrypt(byte[] encrypted, byte[] aesKey) { |
| | | return Pkcs7Encoder.decode(aes(encrypted, aesKey, Cipher.DECRYPT_MODE)); |
| | | } |
| | | |
| | | /** |
| | | * aseå å¯ |
| | | * |
| | | * @param encrypted å
容 |
| | | * @param aesKey å¯é¥ |
| | | * @param mode æ¨¡å¼ |
| | | * @return byte[] |
| | | */ |
| | | private static byte[] aes(byte[] encrypted, byte[] aesKey, int mode) { |
| | | Assert.isTrue(aesKey.length == 32, "IllegalAesKey, aesKey's length must be 32"); |
| | | try { |
| | | Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); |
| | | SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); |
| | | IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16)); |
| | | cipher.init(mode, keySpec, iv); |
| | | return cipher.doFinal(encrypted); |
| | | } catch (Exception e) { |
| | | throw Exceptions.unchecked(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æä¾åºäºPKCS7ç®æ³çå è§£å¯æ¥å£. |
| | | */ |
| | | private static class Pkcs7Encoder { |
| | | private static final int BLOCK_SIZE = 32; |
| | | |
| | | private static byte[] encode(byte[] src) { |
| | | int count = src.length; |
| | | // 计ç®éè¦å¡«å
ç使° |
| | | int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE); |
| | | // è·å¾è¡¥ä½æç¨çå符 |
| | | byte pad = (byte) (amountToPad & 0xFF); |
| | | byte[] pads = new byte[amountToPad]; |
| | | for (int index = 0; index < amountToPad; index++) { |
| | | pads[index] = pad; |
| | | } |
| | | int length = count + amountToPad; |
| | | byte[] dest = new byte[length]; |
| | | System.arraycopy(src, 0, dest, 0, count); |
| | | System.arraycopy(pads, 0, dest, count, amountToPad); |
| | | return dest; |
| | | } |
| | | |
| | | private static byte[] decode(byte[] decrypted) { |
| | | int pad = decrypted[decrypted.length - 1]; |
| | | if (pad < 1 || pad > BLOCK_SIZE) { |
| | | pad = 0; |
| | | } |
| | | if (pad > 0) { |
| | | return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); |
| | | } |
| | | return decrypted; |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.util.AntPathMatcher; |
| | | import org.springframework.util.PathMatcher; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileFilter; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * Spring AntPath è§åæä»¶è¿æ»¤ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @AllArgsConstructor |
| | | public class AntPathFilter implements FileFilter, Serializable { |
| | | private static final long serialVersionUID = 812598009067554612L; |
| | | private static final PathMatcher PATH_MATCHER = new AntPathMatcher(); |
| | | |
| | | private final String pattern; |
| | | |
| | | /** |
| | | * è¿æ»¤è§å |
| | | * |
| | | * @param pathname è·¯å¾ |
| | | * @return boolean |
| | | */ |
| | | @Override |
| | | public boolean accept(File pathname) { |
| | | String filePath = pathname.getAbsolutePath(); |
| | | return PATH_MATCHER.match(pattern, filePath); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | /** |
| | | * Base64å·¥å
· |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class Base64Util extends org.springframework.util.Base64Utils { |
| | | |
| | | /** |
| | | * ç¼ç |
| | | * |
| | | * @param value å符串 |
| | | * @return {String} |
| | | */ |
| | | public static String encode(String value) { |
| | | return Base64Util.encode(value, Charsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * ç¼ç |
| | | * |
| | | * @param value å符串 |
| | | * @param charset å符é |
| | | * @return {String} |
| | | */ |
| | | public static String encode(String value, java.nio.charset.Charset charset) { |
| | | byte[] val = value.getBytes(charset); |
| | | return new String(Base64Util.encode(val), charset); |
| | | } |
| | | |
| | | /** |
| | | * ç¼ç URLå®å
¨ |
| | | * |
| | | * @param value å符串 |
| | | * @return {String} |
| | | */ |
| | | public static String encodeUrlSafe(String value) { |
| | | return Base64Util.encodeUrlSafe(value, Charsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * ç¼ç URLå®å
¨ |
| | | * |
| | | * @param value å符串 |
| | | * @param charset å符é |
| | | * @return {String} |
| | | */ |
| | | public static String encodeUrlSafe(String value, java.nio.charset.Charset charset) { |
| | | byte[] val = value.getBytes(charset); |
| | | return new String(Base64Util.encodeUrlSafe(val), charset); |
| | | } |
| | | |
| | | /** |
| | | * è§£ç |
| | | * |
| | | * @param value å符串 |
| | | * @return {String} |
| | | */ |
| | | public static String decode(String value) { |
| | | return Base64Util.decode(value, Charsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * è§£ç |
| | | * |
| | | * @param value å符串 |
| | | * @param charset å符é |
| | | * @return {String} |
| | | */ |
| | | public static String decode(String value, java.nio.charset.Charset charset) { |
| | | byte[] val = value.getBytes(charset); |
| | | byte[] decodedValue = Base64Util.decode(val); |
| | | return new String(decodedValue, charset); |
| | | } |
| | | |
| | | /** |
| | | * è§£ç URLå®å
¨ |
| | | * |
| | | * @param value å符串 |
| | | * @return {String} |
| | | */ |
| | | public static String decodeUrlSafe(String value) { |
| | | return Base64Util.decodeUrlSafe(value, Charsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * è§£ç URLå®å
¨ |
| | | * |
| | | * @param value å符串 |
| | | * @param charset å符é |
| | | * @return {String} |
| | | */ |
| | | public static String decodeUrlSafe(String value, java.nio.charset.Charset charset) { |
| | | byte[] val = value.getBytes(charset); |
| | | byte[] decodedValue = Base64Util.decodeUrlSafe(val); |
| | | return new String(decodedValue, charset); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | |
| | | import org.springblade.core.tool.beans.BeanProperty; |
| | | import org.springblade.core.tool.beans.BladeBeanCopier; |
| | | import org.springblade.core.tool.beans.BladeBeanMap; |
| | | import org.springblade.core.tool.convert.BladeConverter; |
| | | import org.springframework.beans.BeanWrapper; |
| | | import org.springframework.beans.BeansException; |
| | | import org.springframework.beans.PropertyAccessorFactory; |
| | | import org.springframework.cglib.beans.BeanGenerator; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * å®ä½å·¥å
·ç±» |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class BeanUtil extends org.springframework.beans.BeanUtils { |
| | | |
| | | /** |
| | | * å®ä¾å对象 |
| | | * |
| | | * @param clazz ç±» |
| | | * @param <T> æ³åæ è®° |
| | | * @return 对象 |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <T> T newInstance(Class<?> clazz) { |
| | | return (T) instantiateClass(clazz); |
| | | } |
| | | |
| | | /** |
| | | * å®ä¾å对象 |
| | | * |
| | | * @param clazzStr ç±»å |
| | | * @param <T> æ³åæ è®° |
| | | * @return 对象 |
| | | */ |
| | | public static <T> T newInstance(String clazzStr) { |
| | | try { |
| | | Class<?> clazz = ClassUtil.forName(clazzStr, null); |
| | | return newInstance(clazz); |
| | | } catch (ClassNotFoundException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åBeanç屿§, æ¯æ propertyName å¤çº§ ï¼test.user.name |
| | | * |
| | | * @param bean bean |
| | | * @param propertyName 屿§å |
| | | * @return 屿§å¼ |
| | | */ |
| | | @Nullable |
| | | public static Object getProperty(@Nullable Object bean, String propertyName) { |
| | | if (bean == null) { |
| | | return null; |
| | | } |
| | | BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean); |
| | | return beanWrapper.getPropertyValue(propertyName); |
| | | } |
| | | |
| | | /** |
| | | * 设置Bean屿§, æ¯æ propertyName å¤çº§ ï¼test.user.name |
| | | * |
| | | * @param bean bean |
| | | * @param propertyName 屿§å |
| | | * @param value 屿§å¼ |
| | | */ |
| | | public static void setProperty(Object bean, String propertyName, Object value) { |
| | | Objects.requireNonNull(bean, "bean Could not null"); |
| | | BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean); |
| | | beanWrapper.setPropertyValue(propertyName, value); |
| | | } |
| | | |
| | | /** |
| | | * æ·±å¤å¶ |
| | | * |
| | | * <p> |
| | | * æ¯æ map bean |
| | | * </p> |
| | | * |
| | | * @param source æºå¯¹è±¡ |
| | | * @param <T> æ³åæ è®° |
| | | * @return T |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | @Nullable |
| | | public static <T> T clone(@Nullable T source) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | return (T) BeanUtil.copy(source, source.getClass()); |
| | | } |
| | | |
| | | /** |
| | | * copy å¯¹è±¡å±æ§ï¼é»è®¤ä¸ä½¿ç¨Convert |
| | | * |
| | | * <p> |
| | | * æ¯æ map bean copy |
| | | * </p> |
| | | * |
| | | * @param source æºå¯¹è±¡ |
| | | * @param clazz ç±»å |
| | | * @param <T> æ³åæ è®° |
| | | * @return T |
| | | */ |
| | | @Nullable |
| | | public static <T> T copy(@Nullable Object source, Class<T> clazz) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | return BeanUtil.copy(source, source.getClass(), clazz); |
| | | } |
| | | |
| | | /** |
| | | * copy å¯¹è±¡å±æ§ï¼é»è®¤ä¸ä½¿ç¨Convert |
| | | * |
| | | * <p> |
| | | * æ¯æ map bean copy |
| | | * </p> |
| | | * |
| | | * @param source æºå¯¹è±¡ |
| | | * @param sourceClazz æºç±»å |
| | | * @param targetClazz è½¬æ¢æçç±»å |
| | | * @param <T> æ³åæ è®° |
| | | * @return T |
| | | */ |
| | | @Nullable |
| | | public static <T> T copy(@Nullable Object source, Class sourceClazz, Class<T> targetClazz) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | BladeBeanCopier copier = BladeBeanCopier.create(sourceClazz, targetClazz, false); |
| | | T to = newInstance(targetClazz); |
| | | copier.copy(source, to, null); |
| | | return to; |
| | | } |
| | | |
| | | /** |
| | | * copy å表对象ï¼é»è®¤ä¸ä½¿ç¨Convert |
| | | * |
| | | * <p> |
| | | * æ¯æ map bean copy |
| | | * </p> |
| | | * |
| | | * @param sourceList æºå表 |
| | | * @param targetClazz è½¬æ¢æçç±»å |
| | | * @param <T> æ³åæ è®° |
| | | * @return T |
| | | */ |
| | | public static <T> List<T> copy(@Nullable Collection<?> sourceList, Class<T> targetClazz) { |
| | | if (sourceList == null || sourceList.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | List<T> outList = new ArrayList<>(sourceList.size()); |
| | | Class<?> sourceClazz = null; |
| | | for (Object source : sourceList) { |
| | | if (source == null) { |
| | | continue; |
| | | } |
| | | if (sourceClazz == null) { |
| | | sourceClazz = source.getClass(); |
| | | } |
| | | T bean = BeanUtil.copy(source, sourceClazz, targetClazz); |
| | | outList.add(bean); |
| | | } |
| | | return outList; |
| | | } |
| | | |
| | | /** |
| | | * æ·è´å¯¹è±¡ |
| | | * |
| | | * <p> |
| | | * æ¯æ map bean copy |
| | | * </p> |
| | | * |
| | | * @param source æºå¯¹è±¡ |
| | | * @param targetBean éè¦èµå¼ç对象 |
| | | */ |
| | | public static void copy(@Nullable Object source, @Nullable Object targetBean) { |
| | | if (source == null || targetBean == null) { |
| | | return; |
| | | } |
| | | BladeBeanCopier copier = BladeBeanCopier |
| | | .create(source.getClass(), targetBean.getClass(), false); |
| | | |
| | | copier.copy(source, targetBean, null); |
| | | } |
| | | |
| | | /** |
| | | * æ·è´å¯¹è±¡ï¼source 屿§å null 夿ï¼Map 䏿¯æï¼map ä¼å instanceof 夿ï¼ä¸ä¼ |
| | | * |
| | | * <p> |
| | | * æ¯æ bean copy |
| | | * </p> |
| | | * |
| | | * @param source æºå¯¹è±¡ |
| | | * @param targetBean éè¦èµå¼ç对象 |
| | | */ |
| | | public static void copyNonNull(@Nullable Object source, @Nullable Object targetBean) { |
| | | if (source == null || targetBean == null) { |
| | | return; |
| | | } |
| | | BladeBeanCopier copier = BladeBeanCopier |
| | | .create(source.getClass(), targetBean.getClass(), false, true); |
| | | |
| | | copier.copy(source, targetBean, null); |
| | | } |
| | | |
| | | /** |
| | | * æ·è´å¯¹è±¡å¹¶å¯¹ä¸åç±»å屿§è¿è¡è½¬æ¢ |
| | | * |
| | | * <p> |
| | | * æ¯æ map bean copy |
| | | * </p> |
| | | * |
| | | * @param source æºå¯¹è±¡ |
| | | * @param targetClazz è½¬æ¢æçç±» |
| | | * @param <T> æ³åæ è®° |
| | | * @return T |
| | | */ |
| | | @Nullable |
| | | public static <T> T copyWithConvert(@Nullable Object source, Class<T> targetClazz) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | return BeanUtil.copyWithConvert(source, source.getClass(), targetClazz); |
| | | } |
| | | |
| | | /** |
| | | * æ·è´å¯¹è±¡å¹¶å¯¹ä¸åç±»å屿§è¿è¡è½¬æ¢ |
| | | * |
| | | * <p> |
| | | * æ¯æ map bean copy |
| | | * </p> |
| | | * |
| | | * @param source æºå¯¹è±¡ |
| | | * @param sourceClazz æºç±» |
| | | * @param targetClazz è½¬æ¢æçç±» |
| | | * @param <T> æ³åæ è®° |
| | | * @return T |
| | | */ |
| | | @Nullable |
| | | public static <T> T copyWithConvert(@Nullable Object source, Class<?> sourceClazz, Class<T> targetClazz) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | BladeBeanCopier copier = BladeBeanCopier.create(sourceClazz, targetClazz, true); |
| | | T to = newInstance(targetClazz); |
| | | copier.copy(source, to, new BladeConverter(sourceClazz, targetClazz)); |
| | | return to; |
| | | } |
| | | |
| | | /** |
| | | * æ·è´å表并对ä¸åç±»å屿§è¿è¡è½¬æ¢ |
| | | * |
| | | * <p> |
| | | * æ¯æ map bean copy |
| | | * </p> |
| | | * |
| | | * @param sourceList æºå¯¹è±¡å表 |
| | | * @param targetClazz è½¬æ¢æçç±» |
| | | * @param <T> æ³åæ è®° |
| | | * @return List |
| | | */ |
| | | public static <T> List<T> copyWithConvert(@Nullable Collection<?> sourceList, Class<T> targetClazz) { |
| | | if (sourceList == null || sourceList.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | List<T> outList = new ArrayList<>(sourceList.size()); |
| | | Class<?> sourceClazz = null; |
| | | for (Object source : sourceList) { |
| | | if (source == null) { |
| | | continue; |
| | | } |
| | | if (sourceClazz == null) { |
| | | sourceClazz = source.getClass(); |
| | | } |
| | | T bean = BeanUtil.copyWithConvert(source, sourceClazz, targetClazz); |
| | | outList.add(bean); |
| | | } |
| | | return outList; |
| | | } |
| | | |
| | | /** |
| | | * Copy the property values of the given source bean into the target class. |
| | | * <p>Note: The source and target classes do not have to match or even be derived |
| | | * from each other, as long as the properties match. Any bean properties that the |
| | | * source bean exposes but the target bean does not will silently be ignored. |
| | | * <p>This is just a convenience method. For more complex transfer needs, |
| | | * |
| | | * @param source the source bean |
| | | * @param targetClazz the target bean class |
| | | * @param <T> æ³åæ è®° |
| | | * @return T |
| | | * @throws BeansException if the copying failed |
| | | */ |
| | | @Nullable |
| | | public static <T> T copyProperties(@Nullable Object source, Class<T> targetClazz) throws BeansException { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | T to = newInstance(targetClazz); |
| | | BeanUtil.copyProperties(source, to); |
| | | return to; |
| | | } |
| | | |
| | | /** |
| | | * Copy the property values of the given source bean into the target class. |
| | | * <p>Note: The source and target classes do not have to match or even be derived |
| | | * from each other, as long as the properties match. Any bean properties that the |
| | | * source bean exposes but the target bean does not will silently be ignored. |
| | | * <p>This is just a convenience method. For more complex transfer needs, |
| | | * |
| | | * @param sourceList the source list bean |
| | | * @param targetClazz the target bean class |
| | | * @param <T> æ³åæ è®° |
| | | * @return List |
| | | * @throws BeansException if the copying failed |
| | | */ |
| | | public static <T> List<T> copyProperties(@Nullable Collection<?> sourceList, Class<T> targetClazz) throws BeansException { |
| | | if (sourceList == null || sourceList.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | List<T> outList = new ArrayList<>(sourceList.size()); |
| | | for (Object source : sourceList) { |
| | | if (source == null) { |
| | | continue; |
| | | } |
| | | T bean = BeanUtil.copyProperties(source, targetClazz); |
| | | outList.add(bean); |
| | | } |
| | | return outList; |
| | | } |
| | | |
| | | /** |
| | | * å°å¯¹è±¡è£
æmapå½¢å¼ |
| | | * |
| | | * @param bean æºå¯¹è±¡ |
| | | * @return {Map} |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static Map<String, Object> toMap(@Nullable Object bean) { |
| | | if (bean == null) { |
| | | return new HashMap<>(0); |
| | | } |
| | | return BladeBeanMap.create(bean); |
| | | } |
| | | |
| | | /** |
| | | * å°map 转为 bean |
| | | * |
| | | * @param beanMap map |
| | | * @param valueType 对象类å |
| | | * @param <T> æ³åæ è®° |
| | | * @return {T} |
| | | */ |
| | | public static <T> T toBean(Map<String, Object> beanMap, Class<T> valueType) { |
| | | Objects.requireNonNull(beanMap, "beanMap Could not null"); |
| | | T to = newInstance(valueType); |
| | | if (beanMap.isEmpty()) { |
| | | return to; |
| | | } |
| | | BeanUtil.copy(beanMap, to); |
| | | return to; |
| | | } |
| | | |
| | | /** |
| | | * ç»ä¸ä¸ªBeanæ·»å åæ®µ |
| | | * |
| | | * @param superBean ç¶çº§Bean |
| | | * @param props æ°å¢å±æ§ |
| | | * @return {Object} |
| | | */ |
| | | @Nullable |
| | | public static Object generator(@Nullable Object superBean, BeanProperty... props) { |
| | | if (superBean == null) { |
| | | return null; |
| | | } |
| | | Class<?> superclass = superBean.getClass(); |
| | | Object genBean = generator(superclass, props); |
| | | BeanUtil.copy(superBean, genBean); |
| | | return genBean; |
| | | } |
| | | |
| | | /** |
| | | * ç»ä¸ä¸ªclassæ·»å åæ®µ |
| | | * |
| | | * @param superclass ç¶çº§ |
| | | * @param props æ°å¢å±æ§ |
| | | * @return {Object} |
| | | */ |
| | | public static Object generator(Class<?> superclass, BeanProperty... props) { |
| | | BeanGenerator generator = new BeanGenerator(); |
| | | generator.setSuperclass(superclass); |
| | | generator.setUseCache(true); |
| | | for (BeanProperty prop : props) { |
| | | generator.addProperty(prop.getName(), prop.getType()); |
| | | } |
| | | return generator.create(); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | /** |
| | | * char 叏鿱 |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public interface CharPool { |
| | | |
| | | // @formatter:off |
| | | char UPPER_A = 'A'; |
| | | char LOWER_A = 'a'; |
| | | char UPPER_Z = 'Z'; |
| | | char LOWER_Z = 'z'; |
| | | char DOT = '.'; |
| | | char AT = '@'; |
| | | char LEFT_BRACE = '{'; |
| | | char RIGHT_BRACE = '}'; |
| | | char LEFT_BRACKET = '('; |
| | | char RIGHT_BRACKET = ')'; |
| | | char DASH = '-'; |
| | | char PERCENT = '%'; |
| | | char PIPE = '|'; |
| | | char PLUS = '+'; |
| | | char QUESTION_MARK = '?'; |
| | | char EXCLAMATION_MARK = '!'; |
| | | char EQUALS = '='; |
| | | char AMPERSAND = '&'; |
| | | char ASTERISK = '*'; |
| | | char STAR = ASTERISK; |
| | | char BACK_SLASH = '\\'; |
| | | char COLON = ':'; |
| | | char COMMA = ','; |
| | | char DOLLAR = '$'; |
| | | char SLASH = '/'; |
| | | char HASH = '#'; |
| | | char HAT = '^'; |
| | | char LEFT_CHEV = '<'; |
| | | char NEWLINE = '\n'; |
| | | char N = 'n'; |
| | | char Y = 'y'; |
| | | char QUOTE = '\"'; |
| | | char RETURN = '\r'; |
| | | char TAB = '\t'; |
| | | char RIGHT_CHEV = '>'; |
| | | char SEMICOLON = ';'; |
| | | char SINGLE_QUOTE = '\''; |
| | | char BACKTICK = '`'; |
| | | char SPACE = ' '; |
| | | char TILDA = '~'; |
| | | char LEFT_SQ_BRACKET = '['; |
| | | char RIGHT_SQ_BRACKET = ']'; |
| | | char UNDERSCORE = '_'; |
| | | char ONE = '1'; |
| | | char ZERO = '0'; |
| | | // @formatter:on |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | |
| | | import java.nio.charset.Charset; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.nio.charset.UnsupportedCharsetException; |
| | | |
| | | /** |
| | | * å符éå·¥å
·ç±» |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class Charsets { |
| | | |
| | | /** |
| | | * å符éISO-8859-1 |
| | | */ |
| | | public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1; |
| | | public static final String ISO_8859_1_NAME = ISO_8859_1.name(); |
| | | |
| | | /** |
| | | * å符éGBK |
| | | */ |
| | | public static final Charset GBK = Charset.forName(StringPool.GBK); |
| | | public static final String GBK_NAME = GBK.name(); |
| | | |
| | | /** |
| | | * å符éutf-8 |
| | | */ |
| | | public static final Charset UTF_8 = StandardCharsets.UTF_8; |
| | | public static final String UTF_8_NAME = UTF_8.name(); |
| | | |
| | | /** |
| | | * 转æ¢ä¸ºCharset对象 |
| | | * |
| | | * @param charsetName å符éï¼ä¸ºç©ºåè¿åé»è®¤å符é |
| | | * @return Charsets |
| | | * @throws UnsupportedCharsetException ç¼ç 䏿¯æ |
| | | */ |
| | | public static Charset charset(String charsetName) throws UnsupportedCharsetException { |
| | | return StringUtil.isBlank(charsetName) ? Charset.defaultCharset() : Charset.forName(charsetName); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | import org.springframework.core.BridgeMethodResolver; |
| | | import org.springframework.core.DefaultParameterNameDiscoverer; |
| | | import org.springframework.core.MethodParameter; |
| | | import org.springframework.core.ParameterNameDiscoverer; |
| | | import org.springframework.core.annotation.AnnotatedElementUtils; |
| | | import org.springframework.core.annotation.SynthesizingMethodParameter; |
| | | import org.springframework.web.method.HandlerMethod; |
| | | |
| | | import java.lang.annotation.Annotation; |
| | | import java.lang.reflect.Constructor; |
| | | import java.lang.reflect.Method; |
| | | |
| | | /** |
| | | * ç±»æä½å·¥å
· |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class ClassUtil extends org.springframework.util.ClassUtils { |
| | | |
| | | private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); |
| | | |
| | | /** |
| | | * è·åæ¹æ³åæ°ä¿¡æ¯ |
| | | * |
| | | * @param constructor æé å¨ |
| | | * @param parameterIndex åæ°åºå· |
| | | * @return {MethodParameter} |
| | | */ |
| | | public static MethodParameter getMethodParameter(Constructor<?> constructor, int parameterIndex) { |
| | | MethodParameter methodParameter = new SynthesizingMethodParameter(constructor, parameterIndex); |
| | | methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER); |
| | | return methodParameter; |
| | | } |
| | | |
| | | /** |
| | | * è·åæ¹æ³åæ°ä¿¡æ¯ |
| | | * |
| | | * @param method æ¹æ³ |
| | | * @param parameterIndex åæ°åºå· |
| | | * @return {MethodParameter} |
| | | */ |
| | | public static MethodParameter getMethodParameter(Method method, int parameterIndex) { |
| | | MethodParameter methodParameter = new SynthesizingMethodParameter(method, parameterIndex); |
| | | methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER); |
| | | return methodParameter; |
| | | } |
| | | |
| | | /** |
| | | * è·åAnnotation |
| | | * |
| | | * @param method Method |
| | | * @param annotationType 注解类 |
| | | * @param <A> æ³åæ è®° |
| | | * @return {Annotation} |
| | | */ |
| | | public static <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) { |
| | | Class<?> targetClass = method.getDeclaringClass(); |
| | | // The method may be on an interface, but we need attributes from the target class. |
| | | // If the target class is null, the method will be unchanged. |
| | | Method specificMethod = ClassUtil.getMostSpecificMethod(method, targetClass); |
| | | // If we are dealing with method with generic parameters, find the original method. |
| | | specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); |
| | | // å
æ¾æ¹æ³ï¼åæ¾æ¹æ³ä¸çç±» |
| | | A annotation = AnnotatedElementUtils.findMergedAnnotation(specificMethod, annotationType); |
| | | ; |
| | | if (null != annotation) { |
| | | return annotation; |
| | | } |
| | | // è·åç±»ä¸é¢çAnnotationï¼å¯è½å
å«ç»åæ³¨è§£ï¼æ
éç¨springçå·¥å
·ç±» |
| | | return AnnotatedElementUtils.findMergedAnnotation(specificMethod.getDeclaringClass(), annotationType); |
| | | } |
| | | |
| | | /** |
| | | * è·åAnnotation |
| | | * |
| | | * @param handlerMethod HandlerMethod |
| | | * @param annotationType 注解类 |
| | | * @param <A> æ³åæ è®° |
| | | * @return {Annotation} |
| | | */ |
| | | public static <A extends Annotation> A getAnnotation(HandlerMethod handlerMethod, Class<A> annotationType) { |
| | | // å
æ¾æ¹æ³ï¼åæ¾æ¹æ³ä¸çç±» |
| | | A annotation = handlerMethod.getMethodAnnotation(annotationType); |
| | | if (null != annotation) { |
| | | return annotation; |
| | | } |
| | | // è·åç±»ä¸é¢çAnnotationï¼å¯è½å
å«ç»åæ³¨è§£ï¼æ
éç¨springçå·¥å
·ç±» |
| | | Class<?> beanType = handlerMethod.getBeanType(); |
| | | return AnnotatedElementUtils.findMergedAnnotation(beanType, annotationType); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 夿æ¯å¦ææ³¨è§£ Annotation |
| | | * |
| | | * @param method Method |
| | | * @param annotationType 注解类 |
| | | * @param <A> æ³åæ è®° |
| | | * @return {boolean} |
| | | */ |
| | | public static <A extends Annotation> boolean isAnnotated(Method method, Class<A> annotationType) { |
| | | // å
æ¾æ¹æ³ï¼åæ¾æ¹æ³ä¸çç±» |
| | | boolean isMethodAnnotated = AnnotatedElementUtils.isAnnotated(method, annotationType); |
| | | if (isMethodAnnotated) { |
| | | return true; |
| | | } |
| | | // è·åç±»ä¸é¢çAnnotationï¼å¯è½å
å«ç»åæ³¨è§£ï¼æ
éç¨springçå·¥å
·ç±» |
| | | Class<?> targetClass = method.getDeclaringClass(); |
| | | return AnnotatedElementUtils.isAnnotated(targetClass, annotationType); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.lang.reflect.Array; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * éåå·¥å
·ç±» |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class CollectionUtil extends CollectionUtils { |
| | | |
| | | /** |
| | | * Return {@code true} if the supplied Collection is not {@code null} or empty. |
| | | * Otherwise, return {@code false}. |
| | | * |
| | | * @param collection the Collection to check |
| | | * @return whether the given Collection is not empty |
| | | */ |
| | | public static boolean isNotEmpty(@Nullable Collection<?> collection) { |
| | | return !CollectionUtil.isEmpty(collection); |
| | | } |
| | | |
| | | /** |
| | | * Return {@code true} if the supplied Map is not {@code null} or empty. |
| | | * Otherwise, return {@code false}. |
| | | * |
| | | * @param map the Map to check |
| | | * @return whether the given Map is not empty |
| | | */ |
| | | public static boolean isNotEmpty(@Nullable Map<?, ?> map) { |
| | | return !CollectionUtil.isEmpty(map); |
| | | } |
| | | |
| | | /** |
| | | * Check whether the given Array contains the given element. |
| | | * |
| | | * @param array the Array to check |
| | | * @param element the element to look for |
| | | * @param <T> The generic tag |
| | | * @return {@code true} if found, {@code false} else |
| | | */ |
| | | public static <T> boolean contains(@Nullable T[] array, final T element) { |
| | | if (array == null) { |
| | | return false; |
| | | } |
| | | return Arrays.stream(array).anyMatch(x -> ObjectUtil.nullSafeEquals(x, element)); |
| | | } |
| | | |
| | | /** |
| | | * Concatenates 2 arrays |
| | | * |
| | | * @param one æ°ç»1 |
| | | * @param other æ°ç»2 |
| | | * @return æ°æ°ç» |
| | | */ |
| | | public static String[] concat(String[] one, String[] other) { |
| | | return concat(one, other, String.class); |
| | | } |
| | | |
| | | /** |
| | | * Concatenates 2 arrays |
| | | * |
| | | * @param one æ°ç»1 |
| | | * @param other æ°ç»2 |
| | | * @param clazz æ°ç»ç±» |
| | | * @return æ°æ°ç» |
| | | */ |
| | | public static <T> T[] concat(T[] one, T[] other, Class<T> clazz) { |
| | | T[] target = (T[]) Array.newInstance(clazz, one.length + other.length); |
| | | System.arraycopy(one, 0, target, 0, one.length); |
| | | System.arraycopy(other, 0, target, one.length, other.length); |
| | | return target; |
| | | } |
| | | |
| | | /** |
| | | * 对象æ¯å¦ä¸ºæ°ç»å¯¹è±¡ |
| | | * |
| | | * @param obj 对象 |
| | | * @return æ¯å¦ä¸ºæ°ç»å¯¹è±¡ï¼å¦æä¸º{@code null} è¿åfalse |
| | | */ |
| | | public static boolean isArray(Object obj) { |
| | | if (null == obj) { |
| | | return false; |
| | | } |
| | | return obj.getClass().isArray(); |
| | | } |
| | | |
| | | /** |
| | | * ä¸å¯å Set |
| | | * |
| | | * @param es 对象 |
| | | * @param <E> æ³å |
| | | * @return éå |
| | | */ |
| | | @SafeVarargs |
| | | public static <E> Set<E> ofImmutableSet(E... es) { |
| | | Objects.requireNonNull(es, "args es is null."); |
| | | return Arrays.stream(es).collect(Collectors.toSet()); |
| | | } |
| | | |
| | | /** |
| | | * ä¸å¯å List |
| | | * |
| | | * @param es 对象 |
| | | * @param <E> æ³å |
| | | * @return éå |
| | | */ |
| | | @SafeVarargs |
| | | public static <E> List<E> ofImmutableList(E... es) { |
| | | Objects.requireNonNull(es, "args es is null."); |
| | | return Arrays.stream(es).collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * Iterable 转æ¢ä¸ºListéå |
| | | * |
| | | * @param elements Iterable |
| | | * @param <E> æ³å |
| | | * @return éå |
| | | */ |
| | | public static <E> List<E> toList(Iterable<E> elements) { |
| | | Objects.requireNonNull(elements, "elements es is null."); |
| | | if (elements instanceof Collection) { |
| | | return new ArrayList((Collection) elements); |
| | | } |
| | | Iterator<E> iterator = elements.iterator(); |
| | | List<E> list = new ArrayList<>(); |
| | | while (iterator.hasNext()) { |
| | | list.add(iterator.next()); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * å°key value æ°ç»è½¬ä¸º map |
| | | * |
| | | * @param keysValues key value æ°ç» |
| | | * @param <K> key |
| | | * @param <V> value |
| | | * @return map éå |
| | | */ |
| | | public static <K, V> Map<K, V> toMap(Object... keysValues) { |
| | | int kvLength = keysValues.length; |
| | | if (kvLength % 2 != 0) { |
| | | throw new IllegalArgumentException("wrong number of arguments for met, keysValues length can not be odd"); |
| | | } |
| | | Map<K, V> keyValueMap = new HashMap<>(kvLength); |
| | | for (int i = kvLength - 2; i >= 0; i -= 2) { |
| | | Object key = keysValues[i]; |
| | | Object value = keysValues[i + 1]; |
| | | keyValueMap.put((K) key, (V) value); |
| | | } |
| | | return keyValueMap; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.Locale; |
| | | import java.util.Queue; |
| | | import java.util.TimeZone; |
| | | import java.util.concurrent.ConcurrentLinkedQueue; |
| | | |
| | | /** |
| | | * åètomcat8ä¸çå¹¶åDateFormat |
| | | * <p> |
| | | * {@link SimpleDateFormat}ç线ç¨å®å
¨å
è£
å¨ã |
| | | * ä¸ä½¿ç¨ThreadLocalï¼å建足å¤çSimpleDateFormatå¯¹è±¡æ¥æ»¡è¶³å¹¶åæ§è¦æ±ã |
| | | * </p> |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class ConcurrentDateFormat { |
| | | private final String format; |
| | | private final Locale locale; |
| | | private final TimeZone timezone; |
| | | private final Queue<SimpleDateFormat> queue = new ConcurrentLinkedQueue<>(); |
| | | |
| | | private ConcurrentDateFormat(String format, Locale locale, TimeZone timezone) { |
| | | this.format = format; |
| | | this.locale = locale; |
| | | this.timezone = timezone; |
| | | SimpleDateFormat initial = createInstance(); |
| | | queue.add(initial); |
| | | } |
| | | |
| | | public static ConcurrentDateFormat of(String format) { |
| | | return new ConcurrentDateFormat(format, Locale.getDefault(), TimeZone.getDefault()); |
| | | } |
| | | |
| | | public static ConcurrentDateFormat of(String format, TimeZone timezone) { |
| | | return new ConcurrentDateFormat(format, Locale.getDefault(), timezone); |
| | | } |
| | | |
| | | public static ConcurrentDateFormat of(String format, Locale locale, TimeZone timezone) { |
| | | return new ConcurrentDateFormat(format, locale, timezone); |
| | | } |
| | | |
| | | public String format(Date date) { |
| | | SimpleDateFormat sdf = queue.poll(); |
| | | if (sdf == null) { |
| | | sdf = createInstance(); |
| | | } |
| | | String result = sdf.format(date); |
| | | queue.add(sdf); |
| | | return result; |
| | | } |
| | | |
| | | public Date parse(String source) throws ParseException { |
| | | SimpleDateFormat sdf = queue.poll(); |
| | | if (sdf == null) { |
| | | sdf = createInstance(); |
| | | } |
| | | Date result = sdf.parse(source); |
| | | queue.add(sdf); |
| | | return result; |
| | | } |
| | | |
| | | private SimpleDateFormat createInstance() { |
| | | SimpleDateFormat sdf = new SimpleDateFormat(format, locale); |
| | | sdf.setTimeZone(timezone); |
| | | return sdf; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | import org.springblade.core.tool.convert.BladeConversionService; |
| | | import org.springframework.core.convert.TypeDescriptor; |
| | | import org.springframework.core.convert.support.GenericConversionService; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | /** |
| | | * åºäº spring ConversionService ç±»åè½¬æ¢ |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public class ConvertUtil { |
| | | |
| | | /** |
| | | * Convenience operation for converting a source object to the specified targetType. |
| | | * {@link TypeDescriptor#forObject(Object)}. |
| | | * @param source the source object |
| | | * @param targetType the target type |
| | | * @param <T> æ³åæ è®° |
| | | * @return the converted value |
| | | * @throws IllegalArgumentException if targetType is {@code null}, |
| | | * or sourceType is {@code null} but source is not {@code null} |
| | | */ |
| | | @Nullable |
| | | public static <T> T convert(@Nullable Object source, Class<T> targetType) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | if (ClassUtil.isAssignableValue(targetType, source)) { |
| | | return (T) source; |
| | | } |
| | | GenericConversionService conversionService = BladeConversionService.getInstance(); |
| | | return conversionService.convert(source, targetType); |
| | | } |
| | | |
| | | /** |
| | | * Convenience operation for converting a source object to the specified targetType, |
| | | * where the target type is a descriptor that provides additional conversion context. |
| | | * {@link TypeDescriptor#forObject(Object)}. |
| | | * @param source the source object |
| | | * @param sourceType the source type |
| | | * @param targetType the target type |
| | | * @param <T> æ³åæ è®° |
| | | * @return the converted value |
| | | * @throws IllegalArgumentException if targetType is {@code null}, |
| | | * or sourceType is {@code null} but source is not {@code null} |
| | | */ |
| | | @Nullable |
| | | public static <T> T convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | GenericConversionService conversionService = BladeConversionService.getInstance(); |
| | | return (T) conversionService.convert(source, sourceType, targetType); |
| | | } |
| | | |
| | | /** |
| | | * Convenience operation for converting a source object to the specified targetType, |
| | | * where the target type is a descriptor that provides additional conversion context. |
| | | * Simply delegates to {@link #convert(Object, TypeDescriptor, TypeDescriptor)} and |
| | | * encapsulates the construction of the source type descriptor using |
| | | * {@link TypeDescriptor#forObject(Object)}. |
| | | * @param source the source object |
| | | * @param targetType the target type |
| | | * @param <T> æ³åæ è®° |
| | | * @return the converted value |
| | | * @throws IllegalArgumentException if targetType is {@code null}, |
| | | * or sourceType is {@code null} but source is not {@code null} |
| | | */ |
| | | @Nullable |
| | | public static <T> T convert(@Nullable Object source, TypeDescriptor targetType) { |
| | | if (source == null) { |
| | | return null; |
| | | } |
| | | GenericConversionService conversionService = BladeConversionService.getInstance(); |
| | | return (T) conversionService.convert(source, targetType); |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | /** |
| | | * æ°æ®ç±»å转æ¢å·¥å
·ç±» |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class DatatypeConverterUtil { |
| | | |
| | | /** |
| | | * hexææ¬è½¬æ¢ä¸ºäºè¿å¶ |
| | | * |
| | | * @param hexStr hexææ¬ |
| | | * @return byte[] |
| | | */ |
| | | public static byte[] parseHexBinary(String hexStr) { |
| | | final int len = hexStr.length(); |
| | | |
| | | if (len % 2 != 0) { |
| | | throw new IllegalArgumentException("hexBinary needs to be even-length: " + hexStr); |
| | | } |
| | | |
| | | byte[] out = new byte[len / 2]; |
| | | |
| | | for (int i = 0; i < len; i += 2) { |
| | | int h = hexToBin(hexStr.charAt(i)); |
| | | int l = hexToBin(hexStr.charAt(i + 1)); |
| | | if (h == -1 || l == -1) { |
| | | throw new IllegalArgumentException("contains illegal character for hexBinary: " + hexStr); |
| | | } |
| | | |
| | | out[i / 2] = (byte) (h * 16 + l); |
| | | } |
| | | |
| | | return out; |
| | | } |
| | | |
| | | /** |
| | | * hexææ¬è½¬æ¢ä¸ºint |
| | | * |
| | | * @param ch hexææ¬ |
| | | * @return int |
| | | */ |
| | | private static int hexToBin(char ch) { |
| | | if ('0' <= ch && ch <= '9') { |
| | | return ch - '0'; |
| | | } |
| | | if ('A' <= ch && ch <= 'F') { |
| | | return ch - 'A' + 10; |
| | | } |
| | | if ('a' <= ch && ch <= 'f') { |
| | | return ch - 'a' + 10; |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.tool.utils; |
| | | |
| | | import java.time.*; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.time.temporal.Temporal; |
| | | import java.time.temporal.TemporalAccessor; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * DateTime å·¥å
·ç±» |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | public class DateTimeUtil { |
| | | public static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATETIME); |
| | | public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATE); |
| | | public static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_TIME); |
| | | |
| | | /** |
| | | * æ¥ææ¶é´æ ¼å¼å |
| | | * |
| | | * @param temporal æ¶é´ |
| | | * @return æ ¼å¼ååçæ¶é´ |
| | | */ |
| | | public static String formatDateTime(TemporalAccessor temporal) { |
| | | return DATETIME_FORMAT.format(temporal); |
| | | } |
| | | |
| | | /** |
| | | * æ¥ææ¶é´æ ¼å¼å |
| | | * |
| | | * @param temporal æ¶é´ |
| | | * @return æ ¼å¼ååçæ¶é´ |
| | | */ |
| | | public static String formatDate(TemporalAccessor temporal) { |
| | | return DATE_FORMAT.format(temporal); |
| | | } |
| | | |
| | | /** |
| | | * æ¶é´æ ¼å¼å |
| | | * |
| | | * @param temporal æ¶é´ |
| | | * @return æ ¼å¼ååçæ¶é´ |
| | | */ |
| | | public static String formatTime(TemporalAccessor temporal) { |
| | | return TIME_FORMAT.format(temporal); |
| | | } |
| | | |
| | | /** |
| | | * æ¥ææ ¼å¼å |
| | | * |
| | | * @param temporal æ¶é´ |
| | | * @param pattern è¡¨è¾¾å¼ |
| | | * @return æ ¼å¼ååçæ¶é´ |
| | | */ |
| | | public static String format(TemporalAccessor temporal, String pattern) { |
| | | return DateTimeFormatter.ofPattern(pattern).format(temporal); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¶é´ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @param pattern è¡¨è¾¾å¼ |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalDateTime parseDateTime(String dateStr, String pattern) { |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); |
| | | return DateTimeUtil.parseDateTime(dateStr, formatter); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¶é´ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @param formatter DateTimeFormatter |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalDateTime parseDateTime(String dateStr, DateTimeFormatter formatter) { |
| | | return LocalDateTime.parse(dateStr, formatter); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¶é´ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalDateTime parseDateTime(String dateStr) { |
| | | return DateTimeUtil.parseDateTime(dateStr, DateTimeUtil.DATETIME_FORMAT); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¶é´ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @param pattern è¡¨è¾¾å¼ |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalDate parseDate(String dateStr, String pattern) { |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); |
| | | return DateTimeUtil.parseDate(dateStr, formatter); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¶é´ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @param formatter DateTimeFormatter |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalDate parseDate(String dateStr, DateTimeFormatter formatter) { |
| | | return LocalDate.parse(dateStr, formatter); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¥æ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalDate parseDate(String dateStr) { |
| | | return DateTimeUtil.parseDate(dateStr, DateTimeUtil.DATE_FORMAT); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¶é´ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @param pattern æ¶é´æ£å |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalTime parseTime(String dateStr, String pattern) { |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); |
| | | return DateTimeUtil.parseTime(dateStr, formatter); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¶é´ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @param formatter DateTimeFormatter |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalTime parseTime(String dateStr, DateTimeFormatter formatter) { |
| | | return LocalTime.parse(dateStr, formatter); |
| | | } |
| | | |
| | | /** |
| | | * å°å符串转æ¢ä¸ºæ¶é´ |
| | | * |
| | | * @param dateStr æ¶é´å符串 |
| | | * @return æ¶é´ |
| | | */ |
| | | public static LocalTime parseTime(String dateStr) { |
| | | return DateTimeUtil.parseTime(dateStr, DateTimeUtil.TIME_FORMAT); |
| | | } |
| | | |
| | | /** |
| | | * æ¶é´è½¬ Instant |
| | | * |
| | | * @param dateTime æ¶é´ |
| | | * @return Instant |
| | | */ |
| | | public static Instant toInstant(LocalDateTime dateTime) { |
| | | return dateTime.atZone(ZoneId.systemDefault()).toInstant(); |
| | | } |
| | | |
| | | /** |
| | | * Instant 转 æ¶é´ |
| | | * |
| | | * @param instant Instant |
| | | * @return Instant |
| | | */ |
| | | public static LocalDateTime toDateTime(Instant instant) { |
| | | return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); |
| | | } |
| | | |
| | | /** |
| | | * è½¬æ¢æ date |
| | | * |
| | | * @param dateTime LocalDateTime |
| | | * @return Date |
| | | */ |
| | | public static Date toDate(LocalDateTime dateTime) { |
| | | return Date.from(DateTimeUtil.toInstant(dateTime)); |
| | | } |
| | | |
| | | /** |
| | | * æ¯è¾2个æ¶é´å·®ï¼è·¨åº¦æ¯è¾å° |
| | | * |
| | | * @param startInclusive å¼å§æ¶é´ |
| | | * @param endExclusive ç»ææ¶é´ |
| | | * @return æ¶é´é´é |
| | | */ |
| | | public static Duration between(Temporal startInclusive, Temporal endExclusive) { |
| | | return Duration.between(startInclusive, endExclusive); |
| | | } |
| | | |
| | | /** |
| | | * æ¯è¾2个æ¶é´å·®ï¼è·¨åº¦æ¯è¾å¤§ï¼å¹´ææ¥ä¸ºåä½ |
| | | * |
| | | * @param startDate å¼å§æ¶é´ |
| | | * @param endDate ç»ææ¶é´ |
| | | * @return æ¶é´é´é |
| | | */ |
| | | public static Period between(LocalDate startDate, LocalDate endDate) { |
| | | return Period.between(startDate, endDate); |
| | | } |
| | | } |
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/DateUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/DesUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/DigestUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Exceptions.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/FileUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Func.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/HexUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Holder.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ImageUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/IntegerPool.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/IoUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Lazy.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/NumberUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ObjectUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/PathUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/PlaceholderUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ProtostuffUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/RandomType.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ReflectUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/RegexUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ResourceUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/RsaUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/RuntimeUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/SpringUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringPool.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/SuffixFileFilter.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ThreadLocalUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ThreadUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Unchecked.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/UrlUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Version.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/XmlUtil.java
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/yml/YmlPropertyLoaderFactory.java
Source/BladeX-Tool/blade-starter-actuate/README.md
Source/BladeX-Tool/blade-starter-actuate/pom.xml
Source/BladeX-Tool/blade-starter-actuate/src/main/java/org/springblade/core/http/cache/BladeHttpCacheProperties.java
Source/BladeX-Tool/blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheAble.java
Source/BladeX-Tool/blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheConfiguration.java
Source/BladeX-Tool/blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheInterceptor.java
Source/BladeX-Tool/blade-starter-actuate/src/main/java/org/springblade/core/http/cache/HttpCacheService.java
Source/BladeX-Tool/blade-starter-api-crypto/README.md
Source/BladeX-Tool/blade-starter-api-crypto/pom.xml
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/crypto/ApiCrypto.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/crypto/ApiCryptoAes.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/crypto/ApiCryptoDes.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/crypto/ApiCryptoRsa.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/decrypt/ApiDecrypt.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/decrypt/ApiDecryptAes.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/decrypt/ApiDecryptDes.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/decrypt/ApiDecryptRsa.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/encrypt/ApiEncrypt.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/encrypt/ApiEncryptAes.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/encrypt/ApiEncryptDes.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/annotation/encrypt/ApiEncryptRsa.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/bean/CryptoInfoBean.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/bean/DecryptHttpInputMessage.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/config/ApiCryptoConfiguration.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/config/ApiCryptoProperties.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/core/ApiDecryptParamResolver.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/core/ApiDecryptRequestBodyAdvice.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/core/ApiEncryptResponseBodyAdvice.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/enums/CryptoType.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/exception/DecryptBodyFailException.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/exception/EncryptBodyFailException.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/exception/EncryptMethodNotFoundException.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/exception/KeyNotConfiguredException.java
Source/BladeX-Tool/blade-starter-api-crypto/src/main/java/org/springblade/core/api/crypto/util/ApiCryptoUtil.java
Source/BladeX-Tool/blade-starter-auth/pom.xml
Source/BladeX-Tool/blade-starter-auth/src/main/java/org/springblade/core/secure/AuthInfo.java
Source/BladeX-Tool/blade-starter-auth/src/main/java/org/springblade/core/secure/BladeUser.java
Source/BladeX-Tool/blade-starter-auth/src/main/java/org/springblade/core/secure/TokenInfo.java
Source/BladeX-Tool/blade-starter-auth/src/main/java/org/springblade/core/secure/exception/SecureException.java
Source/BladeX-Tool/blade-starter-auth/src/main/java/org/springblade/core/secure/utils/AuthUtil.java
Source/BladeX-Tool/blade-starter-cache/pom.xml
Source/BladeX-Tool/blade-starter-cache/src/main/java/org/springblade/core/cache/config/CacheConfiguration.java
Source/BladeX-Tool/blade-starter-cache/src/main/java/org/springblade/core/cache/constant/CacheConstant.java
Source/BladeX-Tool/blade-starter-cache/src/main/java/org/springblade/core/cache/utils/CacheUtil.java
Source/BladeX-Tool/blade-starter-datascope/pom.xml
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/annotation/DataAuth.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/config/DataScopeConfiguration.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/constant/DataScopeConstant.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/enums/DataScopeEnum.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/exception/DataScopeException.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/handler/BladeDataScopeHandler.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/handler/BladeScopeModelHandler.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/handler/DataScopeHandler.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/handler/ScopeModelHandler.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/interceptor/DataScopeInterceptor.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/model/DataScopeModel.java
Source/BladeX-Tool/blade-starter-datascope/src/main/java/org/springblade/core/datascope/props/DataScopeProperties.java
Source/BladeX-Tool/blade-starter-develop/pom.xml
Source/BladeX-Tool/blade-starter-develop/src/main/java/org/springblade/develop/CodeGenerator.java
Source/BladeX-Tool/blade-starter-develop/src/main/java/org/springblade/develop/constant/DevelopConstant.java
Source/BladeX-Tool/blade-starter-develop/src/main/java/org/springblade/develop/support/BladeCodeGenerator.java
Source/BladeX-Tool/blade-starter-develop/src/main/java/org/springblade/develop/support/BladeTemplateEngine.java
Source/BladeX-Tool/blade-starter-develop/src/main/resources/beetl.properties
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/controller.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/entity.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/entityDTO.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/entityVO.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/feign.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/feignclient.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/mapper.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/mapper.xml.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/service.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/serviceImpl.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/api/wrapper.java.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/code.properties
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/crud/api.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/crud/const.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/crud/crud.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/sub/api.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/sub/const.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/sub/crud.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/sub/sub.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/tree/api.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/tree/const.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/element/tree/crud.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/crud/Modal.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/crud/data.data.ts.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/crud/data.ts.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/crud/index.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/sub/Modal.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/sub/data.data.ts.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/sub/data.ts.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/sub/index.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/sub/sub.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/tree/Modal.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/tree/data.data.ts.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/tree/data.ts.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/lemon/tree/index.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/crud/api.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/crud/const.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/crud/crud.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/sub/api.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/sub/const.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/sub/crud.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/tree/api.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/tree/const.js.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/saber/tree/crud.vue.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/sql/menu.sql.btl
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/sword/action.js.vm
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/sword/add.js.vm
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/sword/edit.js.vm
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/sword/list.js.vm
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/sword/model.js.vm
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/sword/service.js.vm
Source/BladeX-Tool/blade-starter-develop/src/main/resources/templates/sword/view.js.vm
Source/BladeX-Tool/blade-starter-ehcache/pom.xml
Source/BladeX-Tool/blade-starter-ehcache/src/main/java/org/springblade/core/ehcache/EhcacheConfiguration.java
Source/BladeX-Tool/blade-starter-ehcache/src/main/resources/ehcache.xml
Source/BladeX-Tool/blade-starter-excel/pom.xml
Source/BladeX-Tool/blade-starter-excel/src/main/java/org/springblade/core/excel/listener/DataListener.java
Source/BladeX-Tool/blade-starter-excel/src/main/java/org/springblade/core/excel/listener/ImportListener.java
Source/BladeX-Tool/blade-starter-excel/src/main/java/org/springblade/core/excel/support/ExcelException.java
Source/BladeX-Tool/blade-starter-excel/src/main/java/org/springblade/core/excel/support/ExcelImporter.java
Source/BladeX-Tool/blade-starter-excel/src/main/java/org/springblade/core/excel/util/ExcelUtil.java
Source/BladeX-Tool/blade-starter-flowable/pom.xml
Source/BladeX-Tool/blade-starter-flowable/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java
Source/BladeX-Tool/blade-starter-flowable/src/main/java/org/flowable/common/engine/impl/db/LiquibaseBasedSchemaManager.java
Source/BladeX-Tool/blade-starter-flowable/src/main/resources/processes/LeaveProcess.bpmn20.xml
Source/BladeX-Tool/blade-starter-http/pom.xml
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/AsyncCall.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/AsyncCallback.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/BaseAuthenticator.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/CssQuery.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/CssQueryMethodInterceptor.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/DomMapper.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/Exchange.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/FormBuilder.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/HttpRequest.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/HttpResponse.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/LogLevel.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/Method.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/MultipartFormBuilder.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/ResponseSpec.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/RetryInterceptor.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/RetryPolicy.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/Slf4jLogger.java
Source/BladeX-Tool/blade-starter-http/src/main/java/org/springblade/core/http/util/HttpUtil.java
Source/BladeX-Tool/blade-starter-http/src/test/java/org/springblade/core/http/test/BladeProxySelector.java
Source/BladeX-Tool/blade-starter-http/src/test/java/org/springblade/core/http/test/HttpRequestDemo.java
Source/BladeX-Tool/blade-starter-http/src/test/java/org/springblade/core/http/test/HttpRequestProxyTest.java
Source/BladeX-Tool/blade-starter-http/src/test/java/org/springblade/core/http/test/OsChina.java
Source/BladeX-Tool/blade-starter-http/src/test/java/org/springblade/core/http/test/OsChinaTest.java
Source/BladeX-Tool/blade-starter-http/src/test/java/org/springblade/core/http/test/VBlog.java
Source/BladeX-Tool/blade-starter-http/src/test/java/org/springblade/core/http/test/VNews.java
Source/BladeX-Tool/blade-starter-jwt/pom.xml
Source/BladeX-Tool/blade-starter-jwt/src/main/java/org/springblade/core/jwt/JwtUtil.java
Source/BladeX-Tool/blade-starter-jwt/src/main/java/org/springblade/core/jwt/config/JwtConfiguration.java
Source/BladeX-Tool/blade-starter-jwt/src/main/java/org/springblade/core/jwt/config/JwtRedisConfiguration.java
Source/BladeX-Tool/blade-starter-jwt/src/main/java/org/springblade/core/jwt/constant/JwtConstant.java
Source/BladeX-Tool/blade-starter-jwt/src/main/java/org/springblade/core/jwt/props/JwtProperties.java
Source/BladeX-Tool/blade-starter-jwt/src/main/java/org/springblade/core/jwt/serializer/JwtRedisKeySerializer.java
Source/BladeX-Tool/blade-starter-loadbalancer/pom.xml
Source/BladeX-Tool/blade-starter-loadbalancer/src/main/java/org/springblade/core/loadbalancer/config/BladeLoadBalancerConfiguration.java
Source/BladeX-Tool/blade-starter-loadbalancer/src/main/java/org/springblade/core/loadbalancer/constant/LoadBalancerConstant.java
Source/BladeX-Tool/blade-starter-loadbalancer/src/main/java/org/springblade/core/loadbalancer/props/BladeLoadBalancerProperties.java
Source/BladeX-Tool/blade-starter-loadbalancer/src/main/java/org/springblade/core/loadbalancer/rule/GrayscaleEnvPostProcessor.java
Source/BladeX-Tool/blade-starter-loadbalancer/src/main/java/org/springblade/core/loadbalancer/rule/GrayscaleLoadBalancer.java
Source/BladeX-Tool/blade-starter-log/pom.xml
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/annotation/ApiLog.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/aspect/ApiLogAspect.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/aspect/LogTraceAspect.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/aspect/RequestLogAspect.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/config/BladeErrorMvcAutoConfiguration.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/config/BladeLogToolAutoConfiguration.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/constant/EventConstant.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/error/BladeErrorAttributes.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/error/BladeErrorController.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/error/BladeRestExceptionTranslator.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/error/RestExceptionTranslator.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/event/ApiLogEvent.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/event/ApiLogListener.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/event/ErrorLogEvent.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/event/ErrorLogListener.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/event/UsualLogEvent.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/event/UsualLogListener.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/exception/ServiceException.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/feign/ILogClient.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/feign/LogClientFallback.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/filter/LogTraceFilter.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/launch/LogLauncherServiceImpl.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/listener/LoggerStartupListener.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/logger/BladeLogger.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/model/LogAbstract.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/model/LogApi.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/model/LogError.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/model/LogUsual.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/props/BladeRequestLogProperties.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/publisher/ApiLogPublisher.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/publisher/ErrorLogPublisher.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/publisher/UsualLogPublisher.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/utils/ElkPropsUtil.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/utils/LogAbstractUtil.java
Source/BladeX-Tool/blade-starter-log/src/main/java/org/springblade/core/log/utils/LogTraceUtil.java
Source/BladeX-Tool/blade-starter-log/src/main/resources/blade-log.yml
Source/BladeX-Tool/blade-starter-log/src/main/resources/log/logback-dev.xml
Source/BladeX-Tool/blade-starter-log/src/main/resources/log/logback-prod.xml
Source/BladeX-Tool/blade-starter-log/src/main/resources/log/logback-test.xml
Source/BladeX-Tool/blade-starter-metrics/pom.xml
Source/BladeX-Tool/blade-starter-metrics/src/main/java/org/springblade/core/metrics/druid/DruidDataSourceMetadataProviderConfiguration.java
Source/BladeX-Tool/blade-starter-metrics/src/main/java/org/springblade/core/metrics/druid/DruidDataSourcePoolMetadata.java
Source/BladeX-Tool/blade-starter-metrics/src/main/java/org/springblade/core/metrics/sentinel/SentinelMetricsExtension.java
Source/BladeX-Tool/blade-starter-mongo/pom.xml
Source/BladeX-Tool/blade-starter-mongo/src/main/java/org/springblade/core/mongo/config/MongoConfiguration.java
Source/BladeX-Tool/blade-starter-mongo/src/main/java/org/springblade/core/mongo/converter/DBObjectToJsonNodeConverter.java
Source/BladeX-Tool/blade-starter-mongo/src/main/java/org/springblade/core/mongo/converter/JsonNodeToDocumentConverter.java
Source/BladeX-Tool/blade-starter-mongo/src/main/java/org/springblade/core/mongo/utils/JsonNodeInfo.java
Source/BladeX-Tool/blade-starter-mongo/src/main/java/org/springblade/core/mongo/utils/MongoJsonUtils.java
Source/BladeX-Tool/blade-starter-mybatis/pom.xml
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/BladeMetaObjectHandler.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/base/BaseEntity.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/base/BaseService.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/base/BaseServiceImpl.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/config/MybatisPlusConfiguration.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/injector/BladeSqlInjector.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/injector/BladeSqlMethod.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/injector/methods/AbstractInsertMethod.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/injector/methods/InsertIgnore.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/injector/methods/Replace.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/intercept/QueryInterceptor.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/mapper/BladeMapper.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/plugins/BladePaginationInterceptor.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/plugins/QueryInterceptorExecutor.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/plugins/SqlLogInterceptor.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/props/MybatisPlusProperties.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/resolver/PageArgumentResolver.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/service/BladeService.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/service/impl/BladeServiceImpl.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/support/BaseEntityWrapper.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/support/BladePage.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/support/Condition.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/support/Query.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/support/SqlKeyword.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/java/org/springblade/core/mp/utils/PageUtil.java
Source/BladeX-Tool/blade-starter-mybatis/src/main/resources/blade-mybatis.yml
Source/BladeX-Tool/blade-starter-oss/pom.xml
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/AliossTemplate.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/HuaweiObsTemplate.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/MinioTemplate.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/OssTemplate.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/QiniuTemplate.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/TencentCosTemplate.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/config/AliossConfiguration.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/config/HuaweiObsConfiguration.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/config/MinioConfiguration.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/config/OssConfiguration.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/config/QiniuConfiguration.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/config/TencentCosConfiguration.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/enums/OssEnum.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/enums/OssStatusEnum.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/enums/PolicyType.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/model/BladeFile.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/model/MinioItem.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/model/OssFile.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/props/OssProperties.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/rule/BladeOssRule.java
Source/BladeX-Tool/blade-starter-oss/src/main/java/org/springblade/core/oss/rule/OssRule.java
Source/BladeX-Tool/blade-starter-prometheus/pom.xml
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/config/PrometheusConfiguration.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/data/Agent.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/data/ChangeItem.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/data/Config.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/data/Service.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/data/ServiceHealth.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/endpoint/AgentEndpoint.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/endpoint/ServiceEndpoint.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/java/org/springblade/core/prometheus/service/RegistrationService.java
Source/BladeX-Tool/blade-starter-prometheus/src/main/resources/blade-prometheus.yml
Source/BladeX-Tool/blade-starter-redis/pom.xml
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/cache/BladeRedis.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/cache/CacheKey.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/cache/ICacheKey.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/config/BladeRedisCacheAutoConfiguration.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/config/BladeRedisProperties.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/config/BladeRedisSerializerConfigAble.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/config/ProtoStuffSerializerConfiguration.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/config/RateLimiterAutoConfiguration.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/config/RedisAutoCacheManager.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/config/RedisCacheManagerConfig.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/config/RedisTemplateConfiguration.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/lock/BladeLockAutoConfiguration.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/lock/BladeLockProperties.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/lock/LockType.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/lock/RedisLock.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/lock/RedisLockAspect.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/lock/RedisLockClient.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/lock/RedisLockClientImpl.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/ratelimiter/RateLimiter.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/ratelimiter/RateLimiterClient.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/ratelimiter/RateLimiterException.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/ratelimiter/RedisRateLimiterAspect.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/ratelimiter/RedisRateLimiterClient.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/serializer/BytesWrapper.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/serializer/ProtoStuffSerializer.java
Source/BladeX-Tool/blade-starter-redis/src/main/java/org/springblade/core/redis/serializer/RedisKeySerializer.java
Source/BladeX-Tool/blade-starter-redis/src/main/resources/META-INF/scripts/blade_rate_limiter.lua
Source/BladeX-Tool/blade-starter-redis/src/main/resources/additional-spring-configuration-metadata.json
Source/BladeX-Tool/blade-starter-report/pom.xml
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/config/ReportConfiguration.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/datasource/ReportDataSource.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/endpoint/ReportBootEndpoint.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/endpoint/ReportEndpoint.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/entity/ReportFileEntity.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/mapper/ReportFileMapper.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/props/ReportDatabaseProperties.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/props/ReportProperties.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/provider/DatabaseProvider.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/provider/ReportPlaceholderProvider.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/service/IReportFileService.java
Source/BladeX-Tool/blade-starter-report/src/main/java/org/springblade/core/report/service/impl/ReportFileServiceImpl.java
Source/BladeX-Tool/blade-starter-sms/pom.xml
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/AliSmsTemplate.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/QiniuSmsTemplate.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/SmsTemplate.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/TencentSmsTemplate.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/YunpianSmsTemplate.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/config/AliSmsConfiguration.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/config/QiniuSmsConfiguration.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/config/SmsConfiguration.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/config/TencentSmsConfiguration.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/config/YunpianSmsConfiguration.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/constant/SmsConstant.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/enums/SmsEnum.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/enums/SmsStatusEnum.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/model/SmsCode.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/model/SmsData.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/model/SmsInfo.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/model/SmsResponse.java
Source/BladeX-Tool/blade-starter-sms/src/main/java/org/springblade/core/sms/props/SmsProperties.java
Source/BladeX-Tool/blade-starter-social/pom.xml
Source/BladeX-Tool/blade-starter-social/src/main/java/org/springblade/core/social/cache/AuthStateRedisCache.java
Source/BladeX-Tool/blade-starter-social/src/main/java/org/springblade/core/social/config/SocialConfiguration.java
Source/BladeX-Tool/blade-starter-social/src/main/java/org/springblade/core/social/props/SocialProperties.java
Source/BladeX-Tool/blade-starter-social/src/main/java/org/springblade/core/social/utils/SocialUtil.java
Source/BladeX-Tool/blade-starter-social/src/main/resources/blade-social.yml
Source/BladeX-Tool/blade-starter-swagger/pom.xml
Source/BladeX-Tool/blade-starter-swagger/src/main/java/org/springblade/core/swagger/EnableSwagger.java
Source/BladeX-Tool/blade-starter-swagger/src/main/java/org/springblade/core/swagger/SwaggerAutoConfiguration.java
Source/BladeX-Tool/blade-starter-swagger/src/main/java/org/springblade/core/swagger/SwaggerHandlerConfiguration.java
Source/BladeX-Tool/blade-starter-swagger/src/main/java/org/springblade/core/swagger/SwaggerLauncherServiceImpl.java
Source/BladeX-Tool/blade-starter-swagger/src/main/java/org/springblade/core/swagger/SwaggerProperties.java
Source/BladeX-Tool/blade-starter-swagger/src/main/java/org/springblade/core/swagger/SwaggerUtil.java
Source/BladeX-Tool/blade-starter-swagger/src/main/java/org/springblade/core/swagger/SwaggerWebConfiguration.java
Source/BladeX-Tool/blade-starter-swagger/src/main/resources/blade-swagger.yml
Source/BladeX-Tool/blade-starter-tenant/pom.xml
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/BladeTenantHandler.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/BladeTenantHolder.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/BladeTenantId.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/BladeTenantInterceptor.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/BladeTenantProperties.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/TenantId.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/annotation/NonDS.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/annotation/TableExclude.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/annotation/TenantDS.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/annotation/TenantIgnore.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/annotation/TenantParamDS.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/aspect/BladeTenantAspect.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/config/TenantConfiguration.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/config/TenantDataSourceConfiguration.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/constant/TenantBaseConstant.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/dynamic/DsTenantIdProcessor.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/dynamic/TenantDataSource.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/dynamic/TenantDataSourceAnnotationInterceptor.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/dynamic/TenantDataSourceGlobalAdvisor.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/dynamic/TenantDataSourceGlobalInterceptor.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/dynamic/TenantDataSourceHolder.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/dynamic/TenantDataSourceJdbcProvider.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/exception/TenantDataSourceException.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/launcher/TenantLauncherServiceImpl.java
Source/BladeX-Tool/blade-starter-tenant/src/main/java/org/springblade/core/tenant/mp/TenantEntity.java
Source/BladeX-Tool/blade-starter-trace/pom.xml
Source/BladeX-Tool/blade-starter-trace/src/main/java/org/springblade/core/trace/TraceAutoConfiguration.java
Source/BladeX-Tool/blade-starter-trace/src/main/resources/blade-trace.yml
Source/BladeX-Tool/blade-starter-transaction/pom.xml
Source/BladeX-Tool/blade-starter-transaction/src/main/java/org/springblade/core/transaction/annotation/SeataCloudApplication.java
Source/BladeX-Tool/blade-starter-transaction/src/main/java/org/springblade/core/transaction/config/TransactionConfiguration.java
Source/BladeX-Tool/blade-starter-transaction/src/main/resources/blade-transaction.yml
Source/BladeX-Tool/blade-starter-transaction/src/main/resources/file.conf
Source/BladeX-Tool/doc/mvn/mvn命令.md
Source/BladeX-Tool/pom.xml
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/mdm/MDMData.java (已删除)
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/mdm/MDMParamData.java (已删除)
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/mdm/MdmResultData.java (已删除)
Source/UBCS/ubcs-service-api/ubcs-code-api/src/main/java/com/vci/ubcs/code/vo/webserviceModel/mdm/data.json (已删除)
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/CodeSyncUniversalController.java
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/controller/RedirectViewController.java (已删除)
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/CodeMdmInfaceI.java (已删除)
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/CodeMdmInfaceImpl.java (已删除)
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/webService/config/ClassifyConfig.java (已删除)
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/webService/config/MDMInterFaceConfig.java (已删除) |