搜尋

搜尋結果

Spring boot web api 異常處理
科技新知
MacauYeah・2025-10-28

我們在編寫程式時,經常會遇到一些極端的情況,不會經過 function 的方式回傳結果。例如一個 function 原本是提供讀檔功能,但用戶傳入的並不是一個有效的檔案路徑,又或是誰路徑權限不足,無法讀取。這些不正常的結果,並不是原本 function 所協定的回傳值。那麼,我們會拋出異常 Exception ,中斷所有被呼叫中的 function ,讓上層用戶去考慮怎樣處理這個問題。 在 Web API 中,這些 Exception 就更常見。要求用戶傳入的參數,用戶就是有時候少了幾個。覆寫資料的時候,原本的資料已被刪除。但我們現在是經過 Web Api,不能像過去一直向上拋出異常就能通知用戶。我們需要的,是把異常轉成對應的 Http Status Code,讓用戶端可以快速識別異常的類型。 java 異常對應 Http Response Code 其實在 spring boot web 中,要做轉譯,是很簡單的。在定義 java Exception的時候,若有@ResponseStatus,spring boot web 就會自動回應對應的 http error code。 @ResponseStatusHttpStatus.FORBIDDEN public class CustomAuthenticationException extends RuntimeException public CustomAuthenticationException public CustomAuthenticationExceptionString message supermessage; 以後,任何一個地方拋出 CustomAuthenticationException (假設上層沒有人攔截)都會把該 Controller 的結果改為 http 403。Spring boot 也很聰明的,把異常中的 message 隱藏 ,免得有網安的問題。 若我們定義 Exception 時,沒有@ResponseStatus,Controller 就會變成 http 500,例如我在 controller 中拋個常見的 IOException,這次的結果就會變成 http 500。 @GetMappingquot;apiioErrorquot; public String forceIOException throws IOException throw new IOExceptionquot;force io errorquot;; 如果某些時候,我們想使用 java Exception 中的 message 欄位作為報錯信息,讓 http 客戶端,可以通過固定的 message 檔位找到問題訊息,我們可以在application.properties中,加入server.error.includemessage=always。有些特殊情況,在開發模式時 mvn springbootrun ,已經可以見到有 Exception message,但在投産後java jar又看不到。主要因為開發模式中, pom 有 optional springbootdevtools,會自動加入了server.error.includemessage=always,但 mvn package 後就沒有,因為 runtime 沒有 springbootdevtools 的覆蓋。 額外處理 異常處理除了想控制 http status code 外,有時還需要做一些額外處理,例如發出通知郵件等。若想做額外處理,需要另做一個 @RestControllerAdvice 的類,在接到指定的 exception 時,可以轉換不同的 http code ,而且還可以執行額外 java code ,改變 http ResponseBody 。 @RestControllerAdvice public class GlobalExceptionHandler @ExceptionHandlervalue = RuntimeException.class @ResponseStatusHttpStatus.INTERNAL_SERVER_ERROR public Map handleRuntimeExceptionException ex return Map.ofquot;retquot;, false, quot;anyfieldsquot;, ex.getMessage; 但要注意,一旦使用@RestControllerAdvice 後,就要考慮有沒有改變了某些預設的行為。例如上述的@ExceptionHandlervalue = RuntimeException.class,代表所有RuntimException.class的子類,都會歸由該 function 所處理。當然,你也可以多加幾個 function 來處理不同的子類。 Reference springbootwebapivalidate

Visual Studio Code 才是 coding anywhere的基礎?
科技新知
MacauYeah・2025-10-25

筆者過去就有發表過使用 VM docker code server 作為 coding anywhere的基礎, 現時也有一直使用。code server 有效,但對於Web App 開發,仍有所不足。 那個藏在瀏覽器的IDE Code Server 使用 code server 的好處,就是筆者只需要一個有瀏覽器的客戶端,就可以連線到雲上的VM中使用 code server 。不論多重的功夫,交給外部的雲去做,自己的客戶端就可以盡可能輕便。不想自己攪一套code server開發環境?github codespaces in browser 也是一個很類似的替代器。它也是隨時經雲建立一台專用的 VM,之後就可以經瀏覽器進行開發。 一切看來都很好,所有東西都可以在 VM docker 中進行。如果你的 VM docker,可以有齊所有除錯工具,應該就真萬能了。現實就是不太美好,因為雲上的 VM ,docker 中的容器,主要都是沒圖形介面的。如果你想要利用的除錯工具,例如 chrome,你就未必可以順利在 headless VM docker conatiner 中安裝了。很多除錯工具,要麼就需要圖形介面,要麼就要有條件連到本地硬碟,所以筆者就 code server 本身,真的沒有太多解法。 Web App 開發,回到原始的基本步 Visual Studio Code 回到原始的基本步,本地Visual Studio Code VM docker ,就好好地可以利用本地的 chrome 等進行 NodeJs 的除錯。它就跟本地Visual Studio Code 本地開發類似,本地能用的 chrome,可以經過 vscode 連到 VM docker 內,只要Remote Development 插件就可以了。筆者測試過,真的很簡單,vscode連線後,會在你的VM docker 內,安裝一個很細的 client。然後其他事就像本地開發一樣了。Remote Development 除了用自己的VM外,官方還稱它可以連上github codespaces。筆者就未有詳細測試,有興趣的朋友可以建立一個codespaces看看。 雖然 Visual Studio Code 並沒有保證完整地解決所有問題,但至少它提供了一個橋樑可以作為接口開發。coding anywhere 還是有條件實現,只是我們的客戶端並不如一開始的單純,只少要有一個完整的桌面電腦環境OS ,可以做到 port forward,做一些簡單的對接。只是單純的移動端 Web 界面,就未能夠做到那些複雜的跨機轉譯。

比 Java Mail 更簡單的 Spring boot email
科技新知
MacauYeah・2025-10-24

使用 Spring boot 對接 SMTP gateway 發 email ,相對是容易的。 基本上,它就是會使用自建的 org.springframework.mail.javamail. , 對接 javax.mail. jakarta.mail. 以前的所有設定值 ,都可以經 spring.mail.properties. 傳入 例如 spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.ssl.enable=true spring.mail.properties.mail.smtp.socketFactory.port=465 就等於過去 java.util.Properties props = new java.util.Properties; props.putquot;mail.smtp.authquot;, quot;truequot;; props.putquot;mail.smtp.ssl.enablequot;, quot;truequot;; props.putquot;mail.smtp.socketFactory.portquot;, quot;465quot;; 一個最簡單可以連去 google smtp 的簡易 code 如下 ### application.properties spring.mail.host=smtp.gmail.com spring.mail.port=587 spring.mail.username= spring.mail.password= spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true SpringBootEmailApplicationTests.java @SpringBootTest class SpringBootEmailApplicationTests @Autowired private JavaMailSender javaMailSender; @Valuequot;$spring.mail.usernamequot; private String fromAddress; private static final Logger LOG = LoggerFactory.getLoggerSpringBootEmailApplicationTests.class; @Test void contextLoads try SimpleMailMessage mailMessage = new SimpleMailMessage; mailMessage.setFromfromAddress; mailMessage.setToquot;XXXXXXXXquot;; mailMessage.setTextquot;this is backend email trigger for spring bootquot;; mailMessage.setSubjectquot;spring boot test mailquot;; javaMailSender.sendmailMessage; catch Exception e LOG.errorquot;Error while Sending Mailquot;; throw new RuntimeExceptione; github 原始碼 httpsgithub.commacauyeahspringbootdemotreemainspringboottutorialspringbootemail

【CTM 44 周年慶 您快樂所以我快樂】
文化創意
Cheers!・2025-10-20

您要嘅快樂,從 CTM Home Media 開始!新劇、綜藝、好歌、熱門遊戲 每月更新,一個平台滿足晒您想要嘅娛樂 【秋「Gold」戲爽 劇迷至愛】 myTV Gold rarr; 首 12 個月 $48 月《消失的孩子》、《天空之城》等新劇任睇,仲有《悠長假期》、《神啊!請多給我一點時間》 等經典神劇隨時翻睇! myTV SUPER rarr; 低至 $10 月《巨塔之后》、《獨嘉瞓過界指南》、《剪裁魔法師2》、《香港美食匠人》 緊貼最新至 hit 嘅精彩內容! 【芒果 TV 國際 內地熱潮綜藝同步追 】rarr; 首 12 個月 $28 月 《向往的生活・戲如人生》、《初入職場・中醫季》、《海角 88 號》內地嘅熱門綜藝同劇集,第一時間就睇到! 【Blacknut 500 款雲遊戲 】rarr; 首 12 個月 $28 月《秋後的季節》、《阿基里斯:倖存者》、《切爾諾貝利》、《二擊必殺》、《碧波之下》 每月都有新 Game,一家大細齊齊玩 【JOOX 全天候靚歌相伴 仲免本地數據】rarr; $58 月 洪嘉豪《下世愛你》、Ian 陳卓賢《給千億顆星選中的二人》、周殷廷《想和你》等新歌即刻聽!仲有葉倩文《秋來秋去》、譚詠麟《愛在深秋》、張學友《秋意濃》嘅經典金曲聽唔完 屋企有 Home Media,每月都有新驚喜 全家齊齊快樂! ➤➤ 立即下載 :httpss.ctm.netlxBa4➤➤ CTM Home Media 詳情:httpss.ctm.net89nd1

Spring Web 異步 Api
科技新知
MacauYeah・2025-10-18

在設計網頁應用時,總會有某些功能,是特別消耗時間的,例如我們的應用要提供報表,或長時間搜索。如果,我們的 Web Api 的連結,要強制客戶端等待結果,那麼中途斷線需要重做的機會就變得很高,客戶端的體驗一定不太好。 面對這些情況,我們最好就把原本一個 API 功能分為三個 API 去做。 工作生成 API 查詢狀態 API 查詢結果 API 如果大家有信心,可以把2和3混合在一起,對於客戶端,也是一件好事。不過,2,3 因為回傳的結構可能不一樣,分開處理,程式碼會更易讀。 以下,筆者就以一個模擬報表生成的應用,去解釋如何設計可以即時回傳的 API。 source code springbootwebapiasync ReportController.java 詳細解析 假設我們有一個 ReportController,它負責處理與報告生成相關的 HTTP 請求,它提供三個核心 API 端點。 啟動報告生成端點 @PostMappingquot;reportJobcreatequot; public ResponseEntity createJob String uuid = String.formatquot;%d_%squot;, new Date.getTime, UUID.randomUUID.toString; CompletableFuture.runAsync gt; try orderStatus.putuuid, PROCESSING; Thread.sleep10000; 10second simulated delay reportService.genAndSaveReportuuid; orderStatus.putuuid, COMPLETED; catch InterruptedException e Thread.currentThread.interrupt; ; return ResponseEntity .accepted .headerHttpHeaders.LOCATION, quot;reportJobstatusquot; uuid .bodyMap.ofquot;uuidquot;, uuid, quot;status apiquot;, quot;apireportJobstatusquot; uuid, quot;download apiquot;, quot;apireportJobdownloadquot; uuid; 運作原理: 立即生成唯一的 uuid 來標識這次任務 在 CompletableFuture.runAsync 運行長時間的操作。 API 本身即時回傳了 HTTP 202 Accepted 狀態,告訴客戶端請求已被接受但尚未完成 在回傳的結果中,還有提示可以查詢狀態和查詢結果的API。 這種設計避免了 HTTP Gateway Timeout,因為回應是即時的 。 檢查進度端點 @GetMappingquot;reportJobstatusuuidquot; public ResponseEntity getStatus@PathVariablequot;uuidquot; String uuid String status = orderStatus.getuuid; if status == null return ResponseEntity.notFound.build; if COMPLETED.equalsstatus return ResponseEntity.statusHttpStatus.SEE_OTHER return ResponseEntity.ok .headerHttpHeaders.LOCATION, quot;apireportJobdownloadquot; uuid .bodyMap.ofquot;statusquot;, COMPLETED; return ResponseEntity.statusHttpStatus.ACCEPTED .bodyMap.ofquot;statusquot;, PROCESSING; 單純以 map orderStatus.getuuid 查看狀態結果。這個map 必需是多線程下使用還是安全的 ConcurrentHashMap。 下載結果端點 @GetMappingquot;reportJobdownloaduuidquot; public ResponseEntity download@PathVariablequot;uuidquot; String uuid String status = orderStatus.getuuid; if status == null COMPLETED.equalsstatus return ResponseEntity.notFound.build; else 下載檔案 如果大家並不計較是否需要重做失敗的請求,這個例子已經可以簡單地達到即時異步回傳的效果。如果大家還需求考慮請求是否有效完成,就需要用到 message queue 或其他 job server ,這就不是同一個網頁應用的操作範圍。 Reference source code springbootwebapiasync Building a LongRunning Async REST API in Spring Boot with 202 303 Status Codes

秋意染黃秘境 § 白川鄉合掌村 §
環宇搜奇
莫雪・2025-10-12

秋意染黃秘境 sect; 白川鄉合掌村 sect; 秋收時節, 日本名古屋白川鄉合掌村, 一個被群山環繞的小村落, 除了看染黃染紅的 楓葉點綴的山巒和田野之間, 還有一片一片的金黃稻田。 踏入白川鄉, 感覺穿越在日本古時的美好時光, 接觸動人的秋日黃染一片禾稻秋收圖, 與及大自然原始生態風光, 深吸一口禾稻原野之味、 欣賞著仍保留日本原始風貌的田園風光, 還有那裡獨特一座座三角形茅草屋頂傳統合掌造房屋, 手掌般厚度層層厚厚茅草屋頂角在田園間, 在村鎮上, 都那麼可愛又特別, 茅草襯托住田園翠野, 格外清新又獨特 令人驚喜的日本文化人文景觀, 現今這裡保存著 100多座大大小小的合掌造房屋, 是日本規模最大的合掌造集村落。 當天剛巧遇上霧雨, 串串雨珠簾垂絲掛於最外層的 茅草合掌屋, 日間與及最裡層的好像不受水氣影響到, 相信遇上冬雪時屋內一樣可以保曖防風, 只是披上白茫茫雪衣外觀, 成為一處處經典的秘境風境線。 往白川鄉合掌村, 須在「名古屋」站步行大約5分鐘, 在「名鐵巴士中心」搭乘高速巴士前往, 在「白川鄉巴士總站」下車,所需時間約2小時50分鐘。 白川鄉完好地保留了日本原始生態風景, 一處被人 稱為秘境的地方, 於1995年被登錄為 聯合國教科文組織的世界遺產, 稱是一生人一定要去看一次的絕色景點之一。 抵達「白川鄉巴士總站」後, 我們先沿田園靠邊僕斜坡 步行登上「城山天守閣展望台」, 沿坡路上 一片綠意金黃稻田之色、茅草合掌屋點睛其中, 原野風光盡收眼底, , 斜坡一處留下一大片紅葉, 像是捕鋪上一層軟軟地毯迎客往上, 相信樹上黃葉、紅葉剛且更替不久。 抵達山頂展望台, 視野居高更為廣闊, 白川鄉山野村落盡收眼底, 只見山下田園間 禾稻田添上一抺抺金黃, 茅草合掌屋站立其中, 把守添彩, 形成一片和諧亮麗風景圖, 環繞於四周的山巒被霧氣披掛一縷, 更添上白川鄉秘境的迷離色彩。 山頂天守閣上除了盡收山下自然風光外, 也有食店和手信店舖, 隨你逗留閒蕩與買買。 天守閣上閒蕩溜瀏覽完畢, 信步下山穿梭遊走山下村落, 其中「神田家」是規模最大,也是唯一被指定為 國家重要文化財的建築物, 這棟3層樓的住宅 現在己成為一座展覽館, 購票可入內參觀。 地面層大廳中庭處仍保留著展示著昔日的四方木柴明火圍爐, 進入的遊客紛紛靠攏圍爐取暖感受一下 日本江戶時代舊時的生活樣貌, 從二樓古老木窗外望出去的田園風景格外優美。 交通 古屋「名鐵巴士中心」搭乘高速巴士, 直達「白川鄉巴士總站」車程所需時間大約2小時50分鐘 #米蘭 para;斯福爾紮城堡para; # #日本廣島四國櫻花怒放# 其它文章, 詳情請點擊澳門科學館「蒸氣誌電子月刊」 內之「近代中國科學家事蹟及其精神」 httpswww.msc.org.mozhflipbook55STEAMISSUE 本篇文章、相片版權屬作者所有, 經由版權持有人授權CyberCTM.com發表。 聯絡及邀約 irene801802@hotmail.com

【日本。神戶】※景點※ AQUARIUM × ART átoa 神戶水族館 (PART 1)
走遍世界
80後愛旅行✈️・2025-10-12

神戶的 AQUARIUM ✕ ART aacute;toa 水族館位於神戶港旁邊,鄰近美利堅公園與神戶塔。 離遠看就是一棟水泥建築,下車後非常好找! ​ Google map 截圖 建築設計極具現代感,外牆以幾何切割與金屬質感呈現,宛如一件大型藝術品。 ​ Google map 截圖 神戶的 AQUARIUM ✕ ART aacute;toa 是一座融合水族展示與藝術創作的劇場型水族館,打破傳統水族館的框架,讓你彷彿置身於一場沉浸式的視覺與感官盛宴。 ​ ​ 1F 1F │ 美 食 廣 場 一踏入這棟水泥建築,一樓就是美食廣場。 這裡是神戶最大的美食廣場之一,擁有源自神戶的品牌TOOTH TOOTH精選的9間店舖。 涵蓋洋食、漢堡、蛋包飯、章魚燒、拉麵、烤肉盤、甜點及地方特色飲品等。 美食廣場最特別的是這裡的屋頂連接著水族箱的設計,座椅區可以觀賞到水族館內的巨大水槽,是非常特別的用餐環境! ​ 有時間的話真的要到1F的美食廣場吃點東西,坐在這裡頭頂頂著水族箱的水槽底部,魚群在頭頂悠游,真的超夢幻! ​ 1F │ 博 物 館 商 店 除了美食廣場外,一樓還有博物館商店。 這裡販售水族館限定毛絨玩具(如水豚、象龜)、地元品牌聯名商品(如神戸紅茶調配茶)等。 ​ (官網圖片) 我們吃完午餐後,就往上一層出發。 來到二樓才是水族館買票的地方。 ​ ​ ​ 館內共設有八個主題空間,每一區都有其獨特的演出方式與展示形式,宛如踏入電影或舞台劇場景中。