# 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
真實事件要要分工的,

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課差別?

DB城堡/護城河(蓋橋拆橋)/橋上限量-->用連線池取代
- 蓋橋拆橋的動作-> conn=DriverManager.getConnection(DB_URL, USER, PASSWORD);
- 連線池是先把橋蓋好了,
一開始工作是先把東西生出來,
後續幾年開始追求資料庫效能

---
private 是只有這個類可以用
static 表示不需要實體化就能用,有「共享」的特性。
比較有static跟沒有static的差異,一個決定性的不同是**載入記憶體的時機**。
因為一開始就存在於記憶體之中,所以稱為**靜態**(static)。
final 是變成常數,表示不能更改。
>老師是因為只有自己能用才這樣宣告,讓屬性變成常數
>老師都用private static final宣告常數

---
# JNDI

跟程式要連線,不是跟DB
跟datasource要連線池已經蓋好的橋
程式關掉 = 一口氣把橋拆掉
只要是資料的來源,就是DataSource。
Java 透過JNDI將 DataSource記錄到server上,
JNDI是紀錄資訊的地方,
透過查JNDI就能找到DataSource。
使用DataSource就是使用連線池

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應該也要一一樣

* 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"/>
```

# 匯入匯出
新建資料夾裡面再新建一個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

- 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產生物件

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角色

---


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
新增多筆
---

打錯字直接不印出來,不會報錯。
"0" EL會把你轉成int,如果不能轉,會出現error
java不能這樣寫"0"
javascript 數字0和字串0是同個意思
"12" /4 =3,javascript會幫你轉換
El不能跟jqeury混用
---


MVC純放在JSP
headerValues.xxx[0] 陣列
---
p.168
${sessionScope}
sessionScope 其他三個scope都空的情況下,sessionScope可以不用寫,
對應p.175

如果都有相同屬性,且沒寫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

p177
EL 不用寫usebean /scope

---
p167

## JSTL
p157

<% %>不能跟EL混用

之後才新增JSTL
jstl jar
taglib p123


不再使用<% %>
---
p181

只有變數(x)可以更改
prefix="x"
只要確保變數名不要重複
---
JSP裡面JS的script內,可以location.href("/html路徑"
)可以把網頁跳轉到html頁面讓使用者再次確認,
- 作業
delete和update
html一個(讓使用者輸入資料,只有第一個servlet會用到) ,jsp/servlet都建立兩個檔案
---



if.jsp
```
http://localhost:8080/JSP/m13/If.jsp?user=pan&password=1234
網址後面新增?user=pan&password=1234
就能直接跳轉到正確的頁面(歡迎光臨)
```

上面這寫法是錯誤的,執行結果一樣維持錯誤,
密碼正確也是沒反應。
除了${param.password},運算式也要寫在{}裡面
param.password叫做?

可以用多個c:when 來代替else if
p190 JSTL+EL

p172

for (資料型態 變數 : arr/list的變數名稱)

被切割完的字串String,叫做token
把字元分隔成小字串,用逗點、空格、或其他東西分割
,像是split
處理模式跟forEach標籤一樣
---
老師示範寫code
<c:set var="count" value/>
${emp.count}

變數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>
```
---
作業升級



讓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