# servlet & jsp 程度=學習力 * 專注力 * 理解力 * 記憶力 課後複習+作業 老師則授課+解惑 系統程式:非客製化 c/c++不處理資料庫資料 應用程式:客製化 Java,C#,Python,Javascript 1. window app: pc * javax.swing.* * java.awt.* * java.awt.event 2. mobile app:mobile device 3. web app:server (我們在學的) 自學=程式設計的能力(資訊之母) get 查詢/刪除 post 新增/修改 --- GET請求用於獲取資源,而POST請求用於向服務器提交數據。需要注意的是,POST請求可以用於執行CRUD操作中的"創建(Create)"、"更新(Update)"和"刪除(Delete)" --- get有cache,查詢時候會出現舊資料,透過程式關掉cache就能立即秀出新資料。 直接從database抓資料,client透過server跟database抓資料再回傳給client。 出現問題就refresh 網頁 • GET GET的請求應用於從後端取得資料。 • POST • POST 的請求用於提交資料至後端。 PATCH PATCH 的請求用於套用資料至後端修改。 • DELETE DELETE 的請求用於刪除後端指定資料。 HTTP要求(HTTP request) 當我們在瀏覽器發出HTTP要求,就會用到在HTTP協定的規範中定義的不同HTTP請求方法,最常見的有: GET(最常用):請求特定資料 POST:提交資料(例子:註冊帳戶、驗證資料等) PUT:取代特定資料,通常是更新整個資料 PATCH:修改特定資料,通常是更新部分資料 DELETE:刪除特定資料 另外注意,HTML的的表單只能用GET或POST方法,不能以此兩個以外的方法。 ``` 瀏覽器 ----(HTTP request)----> 伺服器 <--> 資料庫 瀏覽器 <----(HTTP response)---- 伺服器 <--> 資料庫 ``` --- * forward ``` client---req-->server(servlet1--req->servlet2)--res-->clint ``` * include ``` client---req-->server (servlet1--req->servlet2--req->servlet1)--res-->clint ``` --- * 我的網頁可以用Facebook登入,於是我去串接Facebook提供的API * 我的網頁要加入客製化的Google Map,於是我去串接Google Map提供的API 我們可以利用這些狀態碼來做錯誤處理。例如在學習XMLhttpresquest時,我們常常會透過if...else判斷status === 200,從而處理錯誤情況: ```=javascript const xhr = new XMLHttpRequest(); xhr.open('get','https://randomuser.me/api/',true); xhr.send(null); //狀態碼:200代表成功。我們利用此狀態碼去做判斷,做到錯誤處理 xhr.onload = () => { if(xhr.status === 200){ console.log(JSON.parse(xhr.responseText)); }else{ console.log('請求失敗!') } } ``` AJAX基本概念: AJAX是一個非同步執行的技術 不用刷新頁面就能更新網頁資料,不能中斷使用者瀏覽網頁 API意思: 程式與程式之間的串接 API接口是一個網址 HTTP協定: 客戶端與伺服器之間傳輸資料的規範 瀏覽器向伺服器提出HTTP要求(GET、POST、DELETE...) 伺服器除了回傳相應資料,也會回傳HTTP狀態碼 ``` <load-on-startup></load-on-startup> 等於 <load-on-startup/> ``` get 透過cache存在browser,不用透過server抓資料,所以速度很快。 --- 沒有初始參數值,不需要寫init() init()生命週期的方法 tomcat關掉的時候執行destroy() 分為有傳ServletConfig config 參數和沒有傳參數的init() String getInitParameter(String name) 第一次呼叫會產生實例 只有生和死時候會呼叫init() 第二次開始不會呼叫, 參數值是String 字串 把參數值(name(key)/value)放到ServletConfig的實例 每一個Servlet對應一個ServletConfig的實例 --- annotation 與 web.xml差別(p.30) 什麼情況用什麼 針對所有用web.xml 針對個別用annotation web.xml比較易懂易讀 --- `@WebServlet 指到urlParttern` @WebServlet(==第一個屬性==urlParttern="/ServletInitParams" , ==第二個屬性==initParams = { ==第一個初始參數值的屬性==@WebInitParam(name="greeting",value="Have a nice day!"), ==第二個初始參數值的屬性==@WebInitParam(name="count",value="3")}) ``` @WebServlet(urlPatterns="/ServletInitParams" , initParams = { @WebInitParam(name="greeting",value="Have a nice day!"), @WebInitParam(name="count",value="3")}) ``` --- csv, json, xml server---->jsno--->>client(JS) 跨公司用xml,而不是json --- <display-name>Servlet 3.0 Web Application</display-name> <context-param> <param-name>centerFile</param-name> <param-value>/res/TrainingCenters.csv</param-value> </context-param> public InitTrainingCenters(){ } public void contextDestroyed(ServletContextEvent sce){} public void contextInitialized(ServletContextEvent sce){} --- public void contextInitialized(ServletContextEvent sce){ ServletContext } --- @SuppressWarnings("unchecked") --- Listener 頃聽/監聽事件的發生,ServletContext物件的生命週期,也就是Web App的生命週期。 把Listener換成Event onclick Listener要怎麼把資料傳給Servlet? 先把資料放在context裡面,用.setAttribute() --- ✏ServletConfig 跟ServletContext 之間的關聯 當tomcat 第一次開啟時,會建立servlet物件,同時也會建立context物件,接著會調用intit有參數的方法,(參數是servletConfig),來初始化 --- src/main/java和webapp是對應的 webapp路徑跟java的urlpattern路徑是相對應的 uniform resource locator (URL) --- Filter 瀏覽器與Servlet/JSP間的仲介者, client端向server端request之前叫做前置 server 向client response之後叫做後置 * Authentication filters 身分驗證 適合用在下request之前 驗證,跟錢有關 * Logging and auditing filters流水帳和監察 Logging 屬於後置,跟錢有關-銀行,記錄到log上,為每一筆交易紀錄log,時間地點做了什麼事, audit把log拿來auditing, auditing用來災害復原、稽核。 * image conversion filters 可以是前置或後置, * data compression filters 資料壓縮,後置 * Encryption filters 亂碼,可以是前置或後置 在資料夾裡面誰在上面誰就先做(先執行) filter間不能有任何關係 如果有邏輯就寫在do/get --- EncodingFilter EncodingFilterDemo (servlet) 用filter解決編碼問題(亂碼) --- ## session 與cookie p.21 一個request + 一個response= 一個生命週期 HTTP = stateless形式的通訊協定 兩種放資料方式:request(太短) /context(太長)跟應用程式同壽,但是太佔空間拉。 購物車:不斷來回才能完成任務,所以有第三種方式,叫做session。 session: C->S端不間斷的一連串的請求與回應組合的 session 產生於於client端第一次向server的請求request,session由server端產生。 session ID是唯一值,且不會重複。 避免跟其他使用者ID重複,避免送錯資訊 --- ### session終止時機: - 30分鐘session就會timeout,想延長session,client端就要再發出請求requst - 利用程式終止session進行:how? client第一次提出需求request>產生session並給他一個ID server回傳時,ID也要跟著傳回去client端 browser要想辦法把ID記錄下來, client第二次提出需求時,ID隨附在舊session上,只要不要超過30分鐘。 不同ID時,server會拒絕存取。 透過ID來判斷是不是同一個session。 --- * boolean is New() true:first time false: 第二次開始 * void invalidate() 讓session失效 * long getCreationTime() 取得session建立的時間 long 表示日期時間(毫秒) new Date 來轉換日期 * long getLasAccessedTime() 取得用戶上次上網(存取)的時間 --- session則是負責暫存client資料 servlet -Listener 就是紀錄和共享資料的功能,根據生命週期分為三種,request, session, 和context --- ### 設定session 有效時間 void setMaxInactiveInterval(int seconds) 個別設定session的有效時間: 只能設定這一次,下一個session又回到預設值30分鐘。 --- ID:6DBA9D12B9E4EED474713F309615F71F Created : Fri Apr 21 09:29:51 CST 2023 Last Accessed : Fri Apr 21 09:29:51 CST 2023 name = pan --- ``` ID : E588CEE70CAAFA63ADF15C242FAAD56C Created : Fri Apr 21 09:43:03 CST 2023 Last Accessed : Fri Apr 21 09:43:03 CST 2023 name = pan age = 44 ``` ``` ID : E588CEE70CAAFA63ADF15C242FAAD56C Created : Fri Apr 21 09:43:03 CST 2023 Last Accessed : Fri Apr 21 09:43:21 CST 2023 name = pan age = 44 height = 177 ``` getSessionInfo.java ```java= @WebServlet("/GetSessionInfo") public class GetSessionInfo extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //設定編碼(萬用寫法) request.setCharacterEncoding("UTF-8"); //取得session HttpSession session = request.getSession(true); //取得資料 String attName = request.getParameter("attrName"); //attName != null表示有名子,attName.length()>0表示有輸入資料 if (attName != null && attName.length() > 0) { String attValue = request.getParameter("attrValue"); //setAttribute把資料存起來 session.setAttribute(attName, attValue); } //MIME response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); //第一次產生時間 Date created = new Date(session.getCreationTime()); //最後一次存取時間 //new Date 透過建構子產生毫秒時間的日期 Date accessed = new Date(session.getLastAccessedTime()); //印出標籤內容 //現在不用out.write寫法,因為IO次數太多,而是用串接寫法 .append()? out.write("<html><body><h2>Session資訊</h2>"); out.write("ID : " + session.getId() + "<br>"); out.write("Created : " + created + "<br>"); out.write("Last Accessed : " + accessed + "<p>"); //getAttributeNames抓session名子和她所有資訊傳到names,Enumeration不能用for each Enumeration<String> names = session.getAttributeNames(); //不知道集合裡面個數所以用while //names.hasMoreElements() 判斷還有沒有元素,取得布林值 while (names.hasMoreElements()) { //hasNext() 是目前用法 //取得下一個Element String name = names.nextElement(); //現在 names.next() //先getAttribute取得Object,再用toString()轉成字串String String value = session.getAttribute(name).toString(); out.write(name + " = " + value + "<br>"); } out.write("</body></html>"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } ``` --- ### cookie session 存在server 端 cookie存在client 端(browser) * 存放位置 記憶體:網頁關掉就消失 硬碟:存在檔案裏面(會有過期時間) 可有可無資料才存放在cookie 主要還是靠Listener>session * cookie以key/value形式儲存 存/紀錄你購物車上收藏的商品 透過cookie來實現客製化服務 記錄使用者喜好來推送廣告,像是商品推薦、對個別使用者打招呼, client端也能把cookie功能關閉 --- 傳回資料像是html,額外資訊放在header * 沒session會顯示The request has no cookies 執行cookie 會抓取上一次session輸入的資訊 步驟: 先run session 取得JSESSIONID = BBCF267B0B55715283B0A4133983BB82 run html 設定key value 再run一次 html顯示上一次輸入的值 GetCookieInfo.java ```java= @WebServlet("/GetCookieInfo") public class GetCookieInfo extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.write("<html><body><h2>Cookie資訊</h2>"); //使用者連上網頁就先取cookie Cookie[] cookies = request.getCookies(); //先判斷是不是null if (cookies != null) //表示cookie內有東西 for (Cookie c : cookies) out.write(c.getName() + " = " + c.getValue() + "<br>"); else //表示cookie內沒有東西 out.write("The request has no cookies"); out.write("</body></html>"); String name = request.getParameter("cookieName"); if (name != null && name.length() > 0) { String value = request.getParameter("cookieValue"); //產生cookie Cookie c = new Cookie(name, value); response.addCookie(c); } } // end of doGet() protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } // end of doPost() } ``` --- ### JSP =JavaServer Pages 用java幫助你產生網頁 JSP 抄襲ASP JSP: 主要是html再崁入script,來產生動態網頁 一個JSP page包括: * html +JS * jsp elements產生動態內容(以<%%>包起來,並以.jsp命名) p.86 網頁內容 String html= 直接拉到對應資料夾>overwrite --- servlet -Listener 就是紀錄和共享資料的功能,根據生命週期分為三種,request, session, 和context 而JSP多一個page,第四種放資料的方式 ``` <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> page 屬性名稱="屬性的值" =左右不要有空白 ``` --- ### JSP directive elements * page * include: include 每一個網頁都有(共同)的內容 * taglib: 先有servlet才有jsp 所以才會import java.servlet --- ``` page里的变量没法从index.jsp传递到test.jsp。只要页面跳转了,它们就不见了。 request里的变量可以跨越forward前后的两页。但是只要刷新页面,它们就重新计算了。 [session]和application里的变量一直在累加,开始还看不出区别,只要关闭浏览器,再次重启浏览器访问这页,session里的变量就重新计算了。 application里的变量一直在累加,除非重启tomcat,否则它会一直变大。 ``` declaration: <%! scriptlets: <% expression: <%= <% , <%= 寫在doGet()裡面 <%! 寫在doGet()外面 第一次產生實例(new)時是0,之後每run一次+1 有+!和沒有的差別? 有!每次都+1,想重置就重啟tomcat 沒!就維持count=1, ```java= <%@ page language="java" contentType="text/html; charset=BIG5" pageEncoding="BIG5"%> <!DOCTYPE html> <html> <head> <meta charset="BIG5"> <title>Insert title here</title> </head> <body> <%--JSP element demo-- --%> <%int count=0; %> <%count++; %> Welcome,your visitor number is //上面這行是template text,放在out.write()引數中 <%=count %> </body> </html> ``` <%%>裡面不能再有<%%> <%= name%>=<%=value%><br> <%= name +"="+ value%><br> --- ### javabean bean=咖啡豆=建立bean類別的物件來存取資料 1. 實做序列化介面 2. 可以有多個建構子,但一定要有一個沒參數的public建構子 3. 類別不會宣告為public,會宣告為private 4. public 的getter/setter方法 bean是在處理java的一個類別 private封裝後寫getter跟setter方法 serializable序列化介面:把大分子轉成小分子。 組合回去叫做deserializable:把小分子轉成大分子。 只能序列化實例變數。 //轉成物件 //把資料轉成字串 //java傳輸資料給javascript, String sb =new StringBean(); sb.setAttribute("sb",sb); >為了要會什麼,就要練習什麼。 --- ### action elements action elements目的是減少jsp scriptlet上的使用,不要用<%,不要混搭 <%=stringBean.getMessage()%> 等於 <jsp:getProperty name="stringBean" property="message" /> <%stringBean.setMessage("Learning JSP is wonderful");%> 等於 <jsp:setProperty name="stringBean" property="message" value="This is a test" /> --- private屬性叫做attribute property屬性指的是setter getter的方法,比方說會去找你的setMessage() 並去掉set 再把M轉成小寫->得到message public double getSubTotal() ->subTotal 表格欄位名稱跟屬性和getter/setter方法屬性對應 ORM=object, relational database 要一對一對應, mapping 映射 真正接輸入資料的是servlet而不是JSP 真實事件要要分工的, ![](https://i.imgur.com/5RjDPuW.png) Servlet充当Controller , jsp 充当 View  Java bean 当然就是Model 了! --- ### JSP的運作機制 - 特性 - 1.translate & complie Container會將JSP中的內容轉譯(translate)成servlet的java檔 再將它編譯(complie)成servlert的.class 後續就同一個servlet的步驟去完成初始化以及針對每個request產生一個獨立的thread **流程如下:** _myJsp.jsp -> (translate) -> myJsp\_jsp.java -> (complie) -> myJsp\_jsp.class -> myJsp_jsp_ 如同servlet只要初始化後,就會針對request去使用thread配置 因此JSP的translate和complie只會發生一次,之後就如同servlet來運作 - 2.更新方式 但JSP較servlet方便的部分為 servlet修改或需要重啟server,但JSP不用 因為JSP受Web Containe所監控 - 3.DD設定 JSP不須像servlet要設定DD 除非有需要orverride init() - 生命週期(即translate後的Servlet API) - jspInit() 如同servlet的init(),可以orverride - jspDestroy() 同servlet的destroy(),可以orverride - __jspService() 同servlet的service(),因此不能orverride - JSP元素類型 JSP提供了下列的表示法,減少了網頁設計者及開發人員的困難 大概分為下列: - Scrriptlet - Java運算式 - 宣告 - 指令 - EL表達式 - action --- 四種認證型式 剛剛講到的login-config 是認證的一種型式 種共有四種: - 1.BASIC 以base64編碼格式去做encoded,安全性較弱 - 2.DIGEST 使用DIGEST較安全的方式登入,但J2EE不完全支援 - 3.CLIENT-CERT 非常安全的機制,但需要公私鑰,通常應用在B2B - 4.FORM 使用合法的HTML建立自訂表單,認證方式最不安全,也沒有提供加密方式 除了FORM之外,其他方式是只要有設定在DD的login-config 自動就會去實作彈出標準的表單登入 --- ### javabean 除了getter/setter/還可以包含boolean isxxx() ```java= //判斷使用者輸入的帳號密碼是不是符合註冊的資料 public boolean isValid() { return "caterpillar".equals(name) && "123456".equals(password); } ``` JSP 網頁最終將轉換為 Servlet,所謂的 JavaBean,實際上也是 Servlet 中的一個物件實例,當你使用 `<jsp: useBean>` 時,實際上就是在宣告一個 JavaBean 的物件,`id` 屬性即是用以指定參考名稱,而 `class` 屬性則是型態名稱。例如若你在 JSP 的頁面中撰寫以下的內容: ``` <jsp:useBean id="user" class="cc.openhome.User" /> ``` 實際在轉譯為 Servlet 之後,會產生以下的程式碼片段: ``` cc.openhome.User user = null; // id="user" 就是產生這邊的user參考名稱 synchronized (request) { user = (cc.openhome.User) _jspx_page_context.getAttribute( "user", PageContext.PAGE_SCOPE); if (user == null){ user = new cc.openhome.User(); _jspx_page_context.setAttribute( "user", user, PageContext.PAGE_SCOPE); } } ``` --- 一個servlet至少會有三個名稱:類別名稱、註冊的servlet名稱、與URI pattern名稱。 --- 4/27 servelet: 負責前端跟server的溝通 MVC 讓你不用jsp/servlet二選一,讓你取他們雙方的優點 商業邏輯:bean :把運算結果讓人用getter存取,但會讓bean太龐大 目前bean只是封裝你要處理的資料。 * model - JavaBean:封裝你要處理的資料 - dao:資料處理 (一個表格寫一個dao) - service:商業邏輯放在裡面(一個功能寫一個service類,一個service可能用到兩個dao) * view * controller (小專案dao /service暫時先放在controller) DB接到資料先回傳到javabean,再傳回servlet servlet forward資料 to jsp ,再丟給client端 --- 老師會教查詢(單筆/多筆) 作業:新增/修改/刪除 多筆資料>ListBean 早上是用寫死在程式上,如何連接到db.property? - 改用連線池方式 跟jdbc課差別? ![](https://i.imgur.com/cRWyY2v.png) DB城堡/護城河(蓋橋拆橋)/橋上限量-->用連線池取代 - 蓋橋拆橋的動作-> conn=DriverManager.getConnection(DB_URL, USER, PASSWORD); - 連線池是先把橋蓋好了, 一開始工作是先把東西生出來, 後續幾年開始追求資料庫效能 ![](https://i.imgur.com/Xv1wH3U.png) --- private 是只有這個類可以用 static 表示不需要實體化就能用,有「共享」的特性。 比較有static跟沒有static的差異,一個決定性的不同是**載入記憶體的時機**。 因為一開始就存在於記憶體之中,所以稱為**靜態**(static)。 final 是變成常數,表示不能更改。 >老師是因為只有自己能用才這樣宣告,讓屬性變成常數 >老師都用private static final宣告常數 ![](https://i.imgur.com/Uwxm65A.png) --- # JNDI ![](https://i.imgur.com/h8x1XBL.png) 跟程式要連線,不是跟DB 跟datasource要連線池已經蓋好的橋 程式關掉 = 一口氣把橋拆掉 只要是資料的來源,就是DataSource。 Java 透過JNDI將 DataSource記錄到server上, JNDI是紀錄資訊的地方, 透過查JNDI就能找到DataSource。 使用DataSource就是使用連線池 ![](https://i.imgur.com/VCuB8lD.png) datasource 跟jdbc都是介面 --- javax.sql.DataSource (extension) --- ## Tomcat 設定JNDI DataSource - context.xml在終止標籤前打 (這裡context指的是JNDI) 透過JNDI去找DataSource (JNDI lookup) - "java:/comp/env/jdbc/xxx" - xxx你取的名子,是對應context.xml和server.xml裡面的name="jdbc/xxx" - context.xml 裡面的global應該也要一一樣 ![](https://i.imgur.com/Bh6pQ9z.png) * context.xml 在context結束標籤前面新增ResourceLink標籤 ``` <ResourceLink type="javax.sql.DataSource" global="jdbc/servdb" name="jdbc/servdb" /> ``` - server.xml 在GlobalNamingResources標籤內,另一個Resource上打 ``` <Resource auth="Container" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" initialSize="5" maxIdle="5" maxTotal="8" maxWaitMillis="-1" name="jdbc/servdb" password="sa1234" poolPreparedStatements="true" type="javax.sql.DataSource" url="jdbc:sqlserver://localhost:1433;databaseName=servdb;TrustServerCertificate=True" username="sa" validationQuery="select 1"/> ``` ![](https://i.imgur.com/0xFHWCh.png) # 匯入匯出 新建資料夾裡面再新建一個workspace資料夾 /新建server/新建 new dynamic project /新建 new servlet測試後 /就能更改server.xml 和context.xml,之後再匯入專案 --- xml規定 根源只能有一個 webxml ->web-app標籤 context ->context標籤 server->server標籤 --- - 單筆執行html檔 - 多筆直接執行servlet檔 --- 作業: empDao 另外產生專案放作業,把單筆和多筆的放進去 一個表格一個bean,一個表格一個dao package com.lcpan.bean com.lcpan.dao (所有sql指令+連線) 至少五個方法 取得所有資料 新增修改刪除查詢兩種(五種) com.lcpan.controller com.lcpan.service ![](https://i.imgur.com/XwtcJc7.jpg) - insert - insert.html->insert.java(servlet)用getParam去接->insert.jsp(網頁上顯示新增成功的訊息->基本), 加分題: 上面顯示新增的欄位 頁面最下面 新增(submit->送進資料庫)/取消按鈕(reset清空) 最下面顯示新增成功 新增不成功:primary key ... 紅字顯示新增不成功 - delete - delete.html->delete.java->delete.jsp - update: update就是先查詢再update - getUpdate.html (update哪一筆資料)->getUpdate.java(servlet查詢)->UpdateData.jsp(不能只顯示,還要有輸入功能:)->update.java(serverlet update)->UpdateData.jsp - 設計那些能改那些不能改,不能改就不要有input輸入框,可以改才有框能輸入, - 除了某幾個,但實際上是全改 - 全set=萬用,有更新沒更新都送到後端 >路徑有關的bug要注意 --- # debug 寫作業就是練習debug的能力 1. complier error (syntax error) IDE上的小紅叉 2. rumtime error * exception error (500最好除錯) * logical error ->trace 追蹤法來除錯 * environment error --- M: 邏輯處理(對業務熟的)又會java(強的人做) V: 前端 C: java 各種action: useBean產生物件 ![](https://i.imgur.com/mOcG9UO.png) EL 只有取,沒有存 用來處理在JSP容器中的資料 JSP只取資料 servlet---(controller)--->JSP controller負責傳資料 request--> C接使用者需求-->M -->D C<--<--M <--D C-->V ( 傳java bean /map 用.或[] 傳list 用[] 資料只分bean和list bean兩種 C扮演dispatch角色 ![](https://i.imgur.com/tjilRe4.png) --- ![](https://i.imgur.com/bkcQqWk.png) ![](https://i.imgur.com/Z1F0de0.png) request.setAttribute("",) ""裡面的對應識別名稱 ,取字串物件的方式 --- .java int rs=0 //rs是顯示更新幾筆 .jsp if(Integer.parseInt(request.getAttribute("rs").toString())==1 新增一筆 .jsp if(Integer.parseInt(request.getAttribute("rs").toString())>=1 新增多筆 --- ![](https://i.imgur.com/XXseLeH.png) 打錯字直接不印出來,不會報錯。 "0" EL會把你轉成int,如果不能轉,會出現error java不能這樣寫"0" javascript 數字0和字串0是同個意思 "12" /4 =3,javascript會幫你轉換 El不能跟jqeury混用 --- ![](https://i.imgur.com/jWCoacJ.png) ![](https://i.imgur.com/PLWmh2n.png) MVC純放在JSP headerValues.xxx[0] 陣列 --- p.168 ${sessionScope} sessionScope 其他三個scope都空的情況下,sessionScope可以不用寫, 對應p.175 ![](https://i.imgur.com/UWSU3k2.png) 如果都有相同屬性,且沒寫scope就會先抓page ``` customer 屬性的值:${customer}<p> ``` 要用下面方式標註scope ``` pageContext.customer = ${pageScope.customer}<br> request.customer = ${requestScope.customer}<br> session.customer = ${sessionScope.customer}<br> application.customer = ${applicationScope.customer} ``` --- p153 ![](https://i.imgur.com/Fo2Mepl.png) p177 EL 不用寫usebean /scope ![](https://i.imgur.com/MwRf0FX.png) --- p167 ![](https://i.imgur.com/7rSh7Q3.png) ## JSTL p157 ![](https://i.imgur.com/ypTJ9g3.png) <% %>不能跟EL混用 ![](https://i.imgur.com/8adxO1Z.png) 之後才新增JSTL jstl jar taglib p123 ![](https://i.imgur.com/74KC5AV.png) ![](https://i.imgur.com/e7kr6MB.png) 不再使用<% %> --- p181 ![](https://i.imgur.com/Ewqv2t8.png) 只有變數(x)可以更改 prefix="x" 只要確保變數名不要重複 --- JSP裡面JS的script內,可以location.href("/html路徑" )可以把網頁跳轉到html頁面讓使用者再次確認, - 作業 delete和update html一個(讓使用者輸入資料,只有第一個servlet會用到) ,jsp/servlet都建立兩個檔案 --- ![](https://i.imgur.com/tdoxui1.png) ![](https://i.imgur.com/5McEm5F.png) ![](https://i.imgur.com/ZSO2YFF.png) if.jsp ``` http://localhost:8080/JSP/m13/If.jsp?user=pan&password=1234 網址後面新增?user=pan&password=1234 就能直接跳轉到正確的頁面(歡迎光臨) ``` ![](https://i.imgur.com/mXMFB6S.png) 上面這寫法是錯誤的,執行結果一樣維持錯誤, 密碼正確也是沒反應。 除了${param.password},運算式也要寫在{}裡面 param.password叫做? ![](https://i.imgur.com/1vr8lT4.png) 可以用多個c:when 來代替else if p190 JSTL+EL ![](https://i.imgur.com/YTWautU.png) p172 ![](https://i.imgur.com/p9g7PbI.png) for (資料型態 變數 : arr/list的變數名稱) ![](https://i.imgur.com/gnZAvkY.png) 被切割完的字串String,叫做token 把字元分隔成小字串,用逗點、空格、或其他東西分割 ,像是split 處理模式跟forEach標籤一樣 --- 老師示範寫code <c:set var="count" value/> ${emp.count} ![](https://i.imgur.com/v2WUNwp.png) 變數status是區域變數,所以只存在foreach標籤內 ``` <c:forEach items="${emps}" var="emp" varStatus="status"> <tr><td>${emp.empno} <td>${emp.ename} <td>${emp.hiredate} <td>${emp.salary} <td>${emp.deptno} <td>${emp.title} <c:set var="count" value="${status.count}"></c:set> //沒寫scope 所以count是page變數, 套用至這個jsp網頁 </c:forEach> </table> <h3>共${count}筆員工資料</h3> ``` --- 作業升級 ![](https://i.imgur.com/McjmyLq.png) ![](https://i.imgur.com/lNopxAG.png) ![](https://i.imgur.com/0w9CzJG.png) 讓JSP顯示所有欄位,不用動bean,取資料時候,在servlet要呼叫dao時(指令後面+join) 單筆資料page 名子做超連結,一樣是單筆查詢,用編號去查詢 *最難 要怎讓名子對應到編號? 新增首頁main page 查詢所有員工資料->模糊查詢 =% =? 姓名關鍵字查詢: 這兩個都跳到右邊的頁面 insert page-insert.html 多兩個欄位:更新和刪除(做成button) 按鈕對應到員工編號 update page- delete page-詢問是否要刪除 (用alert做) 員工姓名:按了跑出編號單比查詢的 page-select單比 部門名稱不能只顯示編號要確切的 要join部門的表 --- Servlet是透過何種介面的何種方法將request傳給JSP網頁 >RequestDispatcher的forward() --- windows +v 儲存你曾經複製過的東西 --- - html 路徑是寫servlet action=路徑 - jsp 路徑是寫html。 - servlet路徑是寫jsp - @WebServlet("/Insert") 對應html-裡面form的action servlet getParameter 像是String empno=request.getParameter("empno") dao -> stmt.set (rs.get(getter)) Servelet 之間才通過 request來傳 dao直接把參數放在方法裡面來存取,不要通過request dao參數不要放request,response 把servlet裡面dao分離出來 --- <a> ${/servelet路徑} button在form裡面,所以自然能連到其他地方,透過action