【Struts2】Ognl表示式
阿新 • • 發佈:2020-09-08
5).OGNL表示式-操作資料空間
O(Object) G(Graphic) N(Navigation) L(Language) 物件 圖 導航語言 作用:通過表示式方式(非Java程式碼)的方式操作指定資料。 特點:(對比EL) ①可以呼叫方法 ②可以存入資料(繫結資料) OGNL可以操作資料空間(物件): 匯入jar: ognl.jar ① ognl向root區的物件中存入資料 Ognl.setValue("root區的物件的屬性名",root區物件,值); ②ognl從root區的物件中獲取資料 Object ognl表示式獲取的結果 = Ognl.getValue("root區物件的屬性名",root區物件); ③呼叫方法 語法: Ognl: "物件.方法名(引數)" 注意: 表示字串 "zxxx" '1000'(如果ognl外部使用雙引號,內部字串使用單引號) ④數學運算和邏輯運算 + - * / % == != ! && || 注意: (1==“1”)忽略資料型別;(10/3結果為3) 數字除運算, 按照java運算規則計算 ⑤Ognl訪問List集合型別資料 語法: ognl: "list集合[i]" ⑥Ognl訪問Map集合元素 語法: ognl: "map物件.key" key不能是純數字內容。 "map物件['key']" key可以數字或者字串。 ⑦Ognl從context區域獲取資料 重點: context區域是一個map結構 key是字串、value物件型別 語法: Ognl表示式: "#key" context中map的value 測試方法: Ognl.getValue("ognl表示式",放入context區的map,root物件);
6).OGNL表示式-值棧(ValueStack)、Struts2值棧的使用+Struts2標籤庫[重點]
(1)值棧 ValueStack(類名) 作用: 封裝ognl的root和context 使用Ognl表示式訪問值棧內部root區中的物件,context中map的key對應的value 值棧相關api: ①獲得值棧物件 ValueStack vs = ActionContext.getContext().getValueStack(); ②獲得root(棧) CompoundRoot root = vs.getRoot(); ③向root中存入物件 root.push(作為root物件); ④獲得context Map<String,Object> context = vs.getContext(); ⑤如果想context中存入資料 context.put("key",值); ⑥值棧物件提供方法 vs.findValue("ognl表示式"), 使用ognl獲得值棧中的資料。 獲取root區屬性值: vs.findValue(“物件屬性”); 獲取ContextMap區value: vs.findValue(“#key”); (2)Struts2值棧的使用+Struts2標籤庫[重點] Struts2對值棧的管理 ①值棧: Context區(資料結構 Map)[重點] "request" RequestMap(相當於HttpServletRequest作用域) "session" SessionMap(相當於HttpSession作用域) "application" ApplicationMap(相當於ServletContext作用域) Root區(資料結構 棧 Stack) 將當前的Action物件放在root區棧頂。 ②struts2標籤庫: 使用: a.引入標籤庫:<%@taglib uri="/struts-tags" prefix="s" %> b.使用property標籤:<s:property value="ognl表示式"></s:property> 作用: a.執行ognl獲得資料 b.將結果展示給瀏覽器 ③總結: a. 向RequestMap中存入值 Map<String,Object> requestMap = (...)vs.getContext().get("request"); requestMap.put("名字key",值); 通過Ognl表示式訪問RequestMap(相當於request作用域) OGNL: "#request.requestmap中的key" b. 向SessionMap存入值 Map<String,Object> sessionMap = (..)vs.getContext().get("session"); sessionMap.put("key",value) 通過Ognl表示式訪問SessionMap(相當於session作用域) OGNL: "#session.sessionMap中的key" c. 通過Ognl表示式訪問當前的Action的屬性值: 注意: Action生命週期是一次請求過程。(請求轉發) OGNL: "Action的屬性名"
7).OGNL表示式-常用的Struts2標籤、及在struts.xml中使用
(1)常用Struts2標籤(在JSP中使用OGNL) ①property 語法: <s:property value="OGNL表示式,值棧的root獲取值,context獲得值"/> 作用: a.執行ognl表示式,獲得資料 b.講結果顯示給瀏覽器。 常用: <s:property value="Action的屬性名"/> [獲得action的屬性值] <s:property value="#request.requestMap的key"/> [獲得相當於request作用域的requestMap的值] <s:property value="#session.sessionmap的key"/> [獲得相當於session作用域的sessionMap的值] 補充: <s:property/> [獲得的值棧的root區棧頂的物件] ②格式化日期 <s:date name="ognl獲得要格式化顯示的日期" format="設定日期格式"/> 日期格式: 年yyyy 月MM 日dd ③判斷 語法: <s:if test="OGNL獲得資料並邏輯判斷1">條件1成立</s:if> <s:elseif test="ognl條件2">條件2成立</s:elseif> <s:else>都不成立</s:else> ④遍歷ListJ集合 <s:iterator value="OGNL被遍歷的集合"> <s:property/>當前被遍歷的物件:被遍歷的當前物件被放在了root區的棧頂位置 <s:property value="當前物件的屬性名"/>當前被遍歷的物件的屬性 </s:iterator> 作用: a. value屬性遍歷集合;b. 遍歷過程中,每個被遍歷的當前物件,暫時放在值棧的root區的棧頂。 屬性介紹: value: OGNL獲得被遍歷集合 begin: 起始下標 end: 截止下標 step: 步長 [配合 begin="0"] status="vs" (vs.index(下標序號); vs.count(排序序號)) 注意: 將vs存入值棧的context中。key="vs" ⑤遍歷Map <s:interator value="ognl獲得map"> 將遍歷的每個當前物件(Map.Entry key+value),放入root棧頂。 展示key: <s:property value="key"/> 獲得value: <s:property value="value"/> </s:interator> ⑥url重寫 <s:url value="請求資源的路徑"></s:url> 作用: a. 自動補全 "/專案名" b. cookie被禁用的請情況下對url進行重寫。(url;jsessionid=1234asdd1234asd); ⑦action請求標籤 語法: s:action name="" namespace="" executeResult="true"></s:action> 作用:向action發起請求,接收伺服器響應的結果。 屬性: name: 請求的action的name namespace: 請求的action的名稱空間namespace executeResult: 是否包含action的執行結果頁面。 (2)Struts2標籤在struts.xml中使用 struts.xml書寫OGNL表示式 ognl在struts.xml獲得root中當前Action的屬性名,作用域對應的map中的值。 語法: ${ognl表示式} 在跳轉路徑中使用超連結傳值:
8).OGNL表示式-值棧的生命週期、及其原理(如何替代作用域)
(1)值棧的生命週期
生命週期: 一次請求過程.
(2)#值棧如何替代作用域的(原理)
原理:值棧的生命週期一次請求過程,但是值棧的context中的sessionMap中的資料可以跨請求存在,是因為其
最終儲存在HttpSession作用域中,HttpSession可跨多次請求。
SessionMap底層原始碼實現:
存入: 講put方法接受的key和value,session.setAttribute(key,value);儲存在session作用域中,。
取出: 講get方法接受key,session.getAttribute(key);,從session作用域中獲的值
9).攔截器(Interceptor)、攔截器棧(組)
(1)攔截器
概念: 攔截瀏覽器請求struts2的Action.
作用(應用): 提取多個Action中的共同程式碼(通用功能),到攔截器中完成。
執行機制:
①請求訪問Action,會先經過攔截器中程式碼。
②請求經過攔截呼叫方法: intercept(ActionInvocation ai)
ai.invoke();//放行action的請求。
攔截器核心工作機制:(類比Filter)
編碼實現攔截器:
①自定義一個類,實現Interceptor介面
public class MyInterceptor implements Interceptor{
//請求到達攔截器的執行方法。(類似filter中doFilter)
intercept(ai){
Action之前執行的程式碼
ai.invoke();//放行請求。
Action執行之後的程式碼
}
}
②註冊配置攔截器(攔截器被struts2管理)
<interceptors>
<intercept name="名字" class=""></intercept>
</interceptors>
③在需要攔截的action中引用攔截器(名字)
④攔截器修改跳轉路徑:
⑤攔截器和Action+跳轉的完整流程。
(2)攔截器棧(組)
攔截器注意事項:
如果aciton引用自定義攔截器的話,預設攔截器就失效了。
struts-default[筆試]
struts.xml中, `extends="struts-default"`
預設攔截器中配置大量struts核心攔截器,(請求引數自動接收,檔案上傳,值棧,編碼設定),如果action要使用這些攔截器,必須繼承struts-default配置檔案的額資訊。而且還要引入Struts預設的攔截器,放到自己定義的攔截器棧的首個位置:
10).Struts應用-檔案的上傳、下載
(1)檔案上傳
步驟:
①瀏覽器頁面(檔案選擇輸入框
a. 檔案輸入框
b. 表單提交方式 post
c. 設定表單以二進位制流提交: form enctyp="multipart/form-data"
②Action接受檔案
public class FileAction{
private File 檔案輸入框的name;
//set get;
}
③在action講接受file物件拷貝儲存在tomcat專案所在的目錄下
//動態獲得伺服器中專案下的資料夾路徑
ServletContext ctx = ServletActionContext.getServletContext();
String realPath = ctx.getRealPath("/upload");//upload資料夾的真實路徑
String fileName = "hehe.jpg";
String filePath = realPath+"/"+fileName;
//headPic檔案----->filePath路徑
OutputStream os = new FileOutputStream(filePath);
BufferedOutputStream bos = new BufferedOutputStream(os);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(headPic));
byte[] bs = new byte[1024];
while(true){
int i = bis.read(bs);//讀入bs陣列多少長度
if(i<0)break;
bos.write(bs, 0, i);
}
bos.flush();
bos.close();
bis.close();
④獲得上傳檔名:
檔案上傳優化
①檔案大小
預設struts接受上傳檔案大小上限: 2M;
<!-- 常量配置設定檔案上傳的大小 -->
<!-- struts.multipart.maxSize=2097152 100M 1位元組*100000000 -->
<constant name="struts.multipart.maxSize" value="100000000"></constant>
②檔名
問題: 檔名在伺服器端衝突。
解決: 使用UUID生成唯一的名字作為檔名。
程式碼: UUID.randomUUID().toString();"1234-1234-asdfg-2345-435"
檔名設計: UUID+".字尾";
③儲存路徑
問題: 儲存檔案的目錄寫死在程式碼中,耦合,不便於維護。
解決辦法: 儲存目錄名轉移到配置檔案。
④ io工具類:commons-io的jar包
檔案拷貝程式碼簡化:FileUtils.copyFile();
(2)檔案下載
使瀏覽器儲存該檔案,而不是解析展示該檔案?
給瀏覽器設定頭資訊: "content-disposition" "attachment;filename=檔案.字尾"
①設定下載;
response.setHeader("content-disposition", "attachment;filename="+fileName);
②讀入伺服器端檔案輸入流
③指向瀏覽器的輸入流
④邊讀邊寫
補充:
對下載的檔名編碼:
URLEncoder.encode(字串,"UTF-8");
11).Struts應用-驗證碼、令牌、日期轉化(String/util.Date/sql.Date)
(1)驗證碼
作用:
①防止機器人登陸,對系統新增無效資訊
②防止機器人,惡意註冊無效使用者資訊
使用java生成驗證碼圖片:
①產生一個隨機驗證碼字串
②如何將字串生成圖片中
public static BufferedImage getSafeCodeImage(String code) throws IOException {
BufferedImage bi = new BufferedImage(80, 30, BufferedImage.TYPE_INT_BGR);
Graphics g = bi.getGraphics();
g.fillRect(0, 0, 80, 30);
g.setColor(Color.BLUE);
g.drawString(code, 20, 12);
/*ImageIO.write(bi, "jpg", new FileOutputStream("D:\\a.jpg"));*/
return bi;
}
public static String getGenerateCode(int n) {
String str = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
Random rd = new Random();
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < n; i++) {
sb.append(str.charAt(rd.nextInt(62)));
}
return sb.toString();
}
在jsp中產生一個驗證碼:
驗證碼工具類:
Hutool(工具包)
匯入hutool的jar包。
CaptchaUtil 功能: 生成隨機驗證碼(字串)、 生成驗證碼圖片,直接通過流寫出
程式碼步驟:
①生成驗證碼物件:
Captcha captcha = CaptchaUtil.createLineCaptcha(寬度,高度,字元個數,干擾線個數);
Captcha captcha = CaptchaUtil.createLineCaptcha(寬度,高度);
②生成驗證碼:
captcha.getCode();//code字串
captcha.write(outputStream);//將驗證碼圖片通過輸出流,寫出到對應位置
jsp使用驗證碼核心思路:依靠image的src,請求生成驗證碼圖片的action,響應寫回去
使用:
(2)Struts2令牌機制
防止表單重複提交
①分發令牌
Struts中給使用者分發令牌方式: <s:token></s:token>
作用:
a. 給使用者的瀏覽器的表單放入一個隨機字串。
b. 將字串(令牌),向session中存入一份。
核心機制:
②驗證令牌
驗證令牌核心機制
編碼步驟:
a. 書寫一個驗證令牌的攔截器(struts已經提供了)
b. 配置令牌攔截器攔截防止重複提交的action
c. Action必須繼承ActionSupport.
(3)日期格式
①java.util.Date和java.sql.Date之間的轉換:
中間值:Date.getTime();
例:
long l = (new java.util.Date()).getTime();
java.sql.Date d = new java.sql.Date(l);
②String格式轉換為日期格式
日期格式化工具: SimpleDateFormat
String s = "1999-9-9";
//1. 建立日期格式化工具,(匹配日期格式)
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
//2. 呼叫轉發方法
Date parse = format.parse(s);