# 0524 Spring MVC 前端直接傳bean到後端,然後persist進資料庫 spring mvc 利用annotation自動幫你轉換資料的型態給前端? packageToScan --- model 1 vc都是jsp Model 1 -從頭到尾都是JSP, 雖然JSP會轉換成Servlet Model2 --- DispatcherServlet(分派): 將請求分派給controller 透過DispatcherServlet接收請求後,再透過HandlerMapping 對應到正確的url 來決定哪個controller來處理 View顯示PDF畫面-讓使用者可以存成PDF格式 view 透過char.js 元件,產生統計圖表,可以根據使用者想要的形式輸出成pdf, excel, 等格式 一個公司(web app)可以有多個部分/總機(DispatcherServlet),每個DispatcherServlet也有各自獨立的分機表/通訊錄(spring 設定檔), 形成spring bean Container(wap WebApplicationContext) DispatcherServlet 先找自己公司小的組態設定檔,找不到才往上一層找大的全公司設定檔 ![](https://hackmd.io/_uploads/HJJKvKiH2.png) ![](https://hackmd.io/_uploads/ry7tPKiS2.png) load-on-startup : (載入順序) servlet 是單一執行序的,會先載入一個記憶體,不會讓第一個載入的人等太久。 spring mvc 設定檔和spring 的設定檔各自獨立,不要共用 spring mvc 一個,spring 一個設定檔 ![](https://hackmd.io/_uploads/rkecvYsS2.png) DispatcherServlet的工作流程: 1.攔截、接收請求 2.根據HandlerMapping的註冊資料(url),來找對應的controller元件 3.呼叫controller元件處理請求,回傳是字串,這裡是ModelAndView 4.根據ViewResoler的註冊資料取得要回應的url 和名稱 5.如果請求成功導向才會顯示View元件 include/forward差別 forward:幫你介紹專案,把東西給你做,讓你自己處理,打算做專案的人去負責處理請求和回應 include:就是把別人包進來一起做, 會員:檢查是付費會員,但是根據付費程度去判斷你的等級,把網站,分不同權限和貢獻度,慢慢把網站分不同等級顯示不同畫面、能使用的功能 ![](https://hackmd.io/_uploads/Sk9qvtsS2.png) https://www.torproject.org/zh-TW/download/ 洋蔥說是很強的瀏覽器 次一級是firefox ![](https://hackmd.io/_uploads/ry7CwFsS3.png) ![](https://hackmd.io/_uploads/HkvADYjHn.png) ![](https://hackmd.io/_uploads/B130DKjSh.png) ![](https://hackmd.io/_uploads/r1ZJdKjrh.png) 會有三個設定檔 web.xml 會由webapplicationInitializer取代 beans.config.xml 通過context-param和listener標籤才能註冊到web.xml內 , >>以後叫RootAppConfig.java註冊,透過GetRootConFigClass() 來設定 mvc-servlet.xml ![](https://hackmd.io/_uploads/S16JOYjH3.png) ![](https://hackmd.io/_uploads/r1zldFsSh.png) 繼承30頁的介面,並改寫31頁的方法 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/support/AbstractAnnotationConfigDispatcherServletInitializer.html ![](https://hackmd.io/_uploads/HyJW_FjH2.png) ![](https://hackmd.io/_uploads/Hyf-uKjH2.png) ![](https://hackmd.io/_uploads/S1UbuFjSn.png) p.34 另一個範例是DemoRoomAction.java --- RootConfig.java會註冊在WebAppInitializar.java WebAppConfig.java會註冊在RootAppConfig.java WebAppInitializar繼承AbstractAnnotationConfigDispatcherServletInitializar 並改寫 1.getRootConfigClasses() 2.getServletConfigClasses() 3.getServletMappings() --- ![](https://hackmd.io/_uploads/BJ2MdFor3.png) 實作去改寫 ![](https://hackmd.io/_uploads/S1lEuYiBn.png) ![](https://hackmd.io/_uploads/SkEN_Yor3.png) ![](https://hackmd.io/_uploads/SyqEOKjH3.png) ![](https://hackmd.io/_uploads/BypEOtiH3.png) java -jar web -war --- Course Examples: https://1drv.ms/f/s!Ans47I9-Pkiv9iwfs-SoD-uXDkPd HomeWork20230602: https://1drv.ms/f/s!Ans47I9-Pkiv9i0GpvJZpX9Acokh --- api: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html ![](https://hackmd.io/_uploads/S1lPOKiB3.png) ![](https://hackmd.io/_uploads/HJED_YiSh.png) ![](https://hackmd.io/_uploads/HJTv_KoBn.png) ![](https://hackmd.io/_uploads/rk4uuKsH3.png) ![](https://hackmd.io/_uploads/rJ9uOFiH3.png) session 跟request在網址上的差別是什麼? Session scope 跨多頁, 瀏覽器沒有關結果就會在 request scope 只有下一頁,關了再開下一次就沒了 https://openhome.cc/Gossip/StudyGossip/abstractThinking.html 把具體的事物,找出他們之中的關聯性,就是抽象化的過程 ![](https://hackmd.io/_uploads/SkxjdFsrn.png) 19頁 ![](https://hackmd.io/_uploads/rJdoutirh.png) ![](https://hackmd.io/_uploads/B1ajuKoBn.png) ![](https://hackmd.io/_uploads/BkX3uKoSn.png) ![](https://hackmd.io/_uploads/Hy82utjHn.png) ![](https://hackmd.io/_uploads/ByDJFYoSn.png) action不能加斜線 ![](https://hackmd.io/_uploads/SJMxYFsrh.png) ![](https://hackmd.io/_uploads/BJveYKjSn.png) 只存活到當頁 他剛剛那個session是在那裡換頁面 http://localhost:8080/SpringMvcProject/hello2.controller?userName= 把網址改成 http://localhost:8080/SpringMvcProject/success.jsp 來測試 status.setComplete(); status.setComplete();//清除session 中@SessionAttributes 設定的names資料 普通java不能跑,但是可以直接給路徑和參數 http://localhost:8080/SpringMvcProject/members/a001 a001 是我們設定的參數 我們在哪裡設定這個參數R members/ xxx ![](https://hackmd.io/_uploads/rJgmYFiS2.png) 在這裡設定 --- ![](https://hackmd.io/_uploads/rJ6mttiH2.png) ![](https://hackmd.io/_uploads/Hkl4FYsBh.png) ![](https://hackmd.io/_uploads/HyxQ4FYoH3.png) ![](https://hackmd.io/_uploads/rkL4YFoBn.png) ![](https://hackmd.io/_uploads/SJ5EFtsSn.png) ![](https://hackmd.io/_uploads/rkA4KKjSh.png) ![](https://hackmd.io/_uploads/BJbrYYjrn.png) 輸入/* +enter產生多行註解 ![](https://hackmd.io/_uploads/SJKrtYjHh.png) https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/CharacterEncodingFilter.html ![](https://hackmd.io/_uploads/SkWLFFsHn.png) ![](https://hackmd.io/_uploads/rkH8FtiS2.png) 丟到meta-inf藏起來,因為會有衝突 因為目前有java組態 會跟xml有衝突 ![](https://hackmd.io/_uploads/SygwYFsS2.png) ![](https://hackmd.io/_uploads/rJmDtYiSn.png) ![](https://hackmd.io/_uploads/S1_vtFsHn.png) ![](https://hackmd.io/_uploads/SycDYKoB3.png) 恢復成使用xml方式 1. 註解WebAppConfig class 上面的三個annotation 2. 將WebAppInitializer的回傳值改為null 3. 把隱藏的xml檔拉回來 恢復成使用xml方式 0. 把原本藏起來的xml移回來到web-inf底下 1. 註解WebAppConfig class 上面的三個annotation 2. 將WebAppInitializer 下的回傳值改回null --- 20230525 ![](https://hackmd.io/_uploads/Hk9G8ohH3.png) web-inf是隱藏資料夾,無法直接存取。要透過特定方法來間接存取 ![](https://hackmd.io/_uploads/SkrE8j2Bh.png) ![](https://hackmd.io/_uploads/rk5NUj3Hh.png) https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/view/InternalResourceViewResolver.html ![](https://hackmd.io/_uploads/BJvS8jnBh.png) ![](https://hackmd.io/_uploads/HyjHLjnSn.png) ![](https://hackmd.io/_uploads/S1eIUsnBn.png) ![](https://hackmd.io/_uploads/rJv8Ij3Sn.png) 他剛剛是說這個可以隨便取嗎 ? 對 ![](https://hackmd.io/_uploads/ByIwLi2Sn.png) 透過那個自訂義的路徑找到那個方法,再return回去form.jsp, 因為設定檔有寫好,所以才能轉跳去jsp頁面 ![](https://hackmd.io/_uploads/SyRPLjnBn.png) ``` <form action="hello2.controller" method="post"> ``` 納為啥這裡(action路徑)不能有 / ![](https://hackmd.io/_uploads/S1gK8ohHn.png) +/ 會讓專案路徑找不到,網址會少一個專案名,會往上一層 你實際run一遍比較清楚 ![](https://hackmd.io/_uploads/ByaK8i3H2.png) https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/hibernate5/HibernateTransactionManager.html ![](https://hackmd.io/_uploads/H1Hq8shB3.png) 剛剛那串算是在做啥 ![](https://hackmd.io/_uploads/rJQ3F0nS2.png) 建立一個交易經理 自動化交易 他幫你管理連線工廠 高鐵站購票網站也是排隊方式(資料庫隔離) ==判斷bean不是null,再把帳號密碼存在bean裡面,在把bean存在session內== 這邊有說判斷bean是否為null就好 就不用每個欄位去判斷然後去set ![](https://hackmd.io/_uploads/HJabqo3S2.png) jsp 英文開頭大小寫打錯,不要直接改檔名的大小寫會找不到,可以在後面加數字01 ### jsp實際存放的位置 //C:\Action\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\SpringMvcProject\org\apache\jsp\WEB_002dINF\pages 這是jsp最後長的樣子ㄇ 對 --- ### sql 指令匯出教學 https://dotblogs.com.tw/SmallFish/2019/11/14/124603 --- Bean 裡面的 ORM技術 + 組態設定檔 + //交易管理員@Transactional 就會自動開啟關閉交易 不需要再begin. rollback ...等 ![](https://hackmd.io/_uploads/r1Rsqo3Hh.png) =:user 所以第一個參數就變成字串,你指定的值 換成=? 下方參數應該可以換成數字 ![](https://hackmd.io/_uploads/SJQ35shrn.png) 另一種寫法 ,在hibernate p.165頁 ![](https://hackmd.io/_uploads/Bkp35inB2.png) 起始頁面的網址: http://localhost:8080/SpringMvcProject/loginsystemmain.controller 1. 透過processMainController方法跳轉到loginSystem.jsp 一旦按下送出 網址會變成: http://localhost:8080/SpringMvcProject/checklogin.controller 2. 執行processAction方法 根據不同情況顯示不同解果,只有輸入成功會跳到另一個頁面, 其他情況都是同一個頁面,只是會顯示錯誤訊息 為什麼一定要執行這個網址才能跑? http://localhost:8080/SpringMvcProject/loginsystemmain.controller 是只要按了Submit就會跳轉到checkLogin.controllerㄇ 不管帳號密碼是否有誤 ![](https://hackmd.io/_uploads/HJwXjshHh.png) 對阿因為 action跳轉頁面 ,但controller 還是return loginSystem 所以錯誤情況才會留在同個頁面 --- @PostMapping("/checkLogin.controller") 因為這個要求Post方法進入 透過post 會把資訊藏在body ,但是網址進入方式是get的方式,方法不符合就會出錯 --- ![](https://hackmd.io/_uploads/rJ9Bjs2Bh.png) 因為左邊有 右邊是多寫的 但是建議都要寫 因為有人可能在root沒有打到 會找不到錯在哪 --- ![](https://hackmd.io/_uploads/S1DOsohSn.png) member.jsp 一樣不能直接執行,要結合javabean,透過controller 去轉發頁面 javabean 屬性對應input path=""的屬性 ![](https://hackmd.io/_uploads/BJ5Ysonrh.png) http://localhost:8080/SpringMvcProject/membersmain.controller ![](https://hackmd.io/_uploads/Bk9qoinSh.png) 沒意外的話會接到一個mem2的Bean物件 可以透過session的persist儲存 ![](https://hackmd.io/_uploads/BJHijjnBn.png) --- 測試網址 http://localhost:8080/SpringMvcProject/membersmain.controller ![](https://hackmd.io/_uploads/BkVtEX0Sn.png) 在src 下建立資料夾 packagename自己取 在建立兩個檔案(不同語系的設定檔,文字內容也不同) messageSource()負責幫你找檔案 setBasename //設定檔名位置 setDefaultEncoding //設定編碼 /** 兩個**代表能往下找多層路徑 LocaleChangeInterceptor() : LCI ![](https://hackmd.io/_uploads/ryaqh60Bh.png) 這是攔截器 ![](https://hackmd.io/_uploads/rkpTnTRHh.png) 可以註冊多個 ![](https://hackmd.io/_uploads/Hk2CnaRS3.png) ![](https://hackmd.io/_uploads/Sk7yp6Ar3.png) ![](https://hackmd.io/_uploads/HyOJ6aCHh.png) 執行 http://localhost:8080/SpringMvcProject/multiLangResult.controller --- 測試路徑只改http://localhost:8080/SpringMvcProject/ 後面的controller路徑 ![](https://hackmd.io/_uploads/SyFGT6AH2.png) ![](https://hackmd.io/_uploads/SyLuppArn.png) css ```=css @charset "UTF-8"; body { font-family: monospace } #red { color: pink; font-size: 2cm } #green { color: skyblue; font-size: 2cm } #blue { color: Teal; font-size: 2cm } ``` ms.setBasename("i18n.message"); //設定檔名位置 (i18n是package name ,message 是語系前面的檔名) 貼左邊網址跳轉到右邊的 ![](https://hackmd.io/_uploads/B1Sna6CH2.png) xml預設是jsp html可能就會找不到 ``` <mvc:default-servlet-handler/> <!-- 支援執行html(xml預設是支援jsp), 沒有加找不到,只有xml組態設定才需要, java程式組態預設可以讀取 --> ``` ![](https://hackmd.io/_uploads/BJIE0a0Hh.png) --- 先載入common io jar 然後再ResponseController 新增方法來讀取圖片 ### 設定jsp跳出提示 ![](https://hackmd.io/_uploads/r1HxkACS3.png) <=.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ --- http://localhost:8080/SpringMvcProject/uploadfilemain.controller --- dao 新增session.flush root 設定檔 新增 props.put("hibernate.allow_update_outside_transaction", Boolean.TRUE); ![](https://hackmd.io/_uploads/BJ0dJA0Bn.png) ![](https://hackmd.io/_uploads/B14YJC0Bn.png) http://localhost:8080/SpringMvcProject/uploadfilemain.controller --- 測試json,利用bean注入然後顯示在網頁上 localhost:8080/SpringMvcProject/jsoncreate2.controller ### postman 測試 ![](https://hackmd.io/_uploads/BydelACrn.png) ![](https://hackmd.io/_uploads/SJgZgCRH3.png) 例外處理,老師故意弄一個錯誤的來測試 http://localhost:8080/SpringMvcProject/myexcept.controller