Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传
一、OGNL概述:OGNL是一種表達(dá)式
(1)在struts2中操作值棧數(shù)據(jù)。
(2)一般把ognl在struts2中操作,和struts2標(biāo)簽一起使用操作值棧。
(3)ognl不是strut2的一部分,是單獨(dú)的項(xiàng)目,經(jīng)常和struts2一起使用。
(4)使用ognl的時(shí)候首先要導(dǎo)入jar包。
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!-- 引入struts2標(biāo)簽 --> <%@ taglib prefix="s" uri="/struts-tags"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>ognl案例</title> </head> <body><!-- ognl+struts2實(shí)現(xiàn)計(jì)算字符串長度 --><!-- value值:ognl表達(dá)式 --><s:property value="'這是一個(gè)字符串'.length()"/> </body> </html>?
?
二、值棧:
1、概述:
(1)值棧是struts2提供的一種存儲(chǔ)機(jī)制,類似于域?qū)ο?#xff0c;可以存值和取值。
(2)Servlet和Action的區(qū)別:
Servlet:默認(rèn)在第一次訪問時(shí)創(chuàng)建,只創(chuàng)建一次,單實(shí)例對(duì)象。
Action:訪問時(shí)候創(chuàng)建,每次訪問action的時(shí)候,都會(huì)創(chuàng)建action對(duì)象,創(chuàng)建多次,多實(shí)例對(duì)象。
(3)值棧存儲(chǔ)位置:
在每個(gè)action對(duì)象里面都會(huì)有一個(gè)值棧對(duì)象(只有一個(gè))
?
2、獲取值棧對(duì)象:
(1)獲取值棧對(duì)象有多種方式,常用方式是:使用ActionContext類里面的方法得到值棧對(duì)象。
(2)每個(gè)action對(duì)象中只有一個(gè)值棧對(duì)象。
public class StackDemoAction extends ActionSupport {public String execute(){//1.獲取ActionContext類的對(duì)象ActionContext context=ActionContext.getContext();//調(diào)用方法獲取值棧對(duì)象:ValueStack stack1=context.getValueStack();ValueStack stack2=context.getValueStack();System.out.println(stack1==stack2);//輸入結(jié)果為truereturn NONE;} }?
3、值棧內(nèi)部結(jié)構(gòu):
(1)值棧一般分為兩部分:
第一部分是root,結(jié)構(gòu)是list集合,一般操作都是root里面的數(shù)據(jù)。
第二部分是context,結(jié)構(gòu)是map集合。
(2)struts2里面標(biāo)簽<s:debug>,使用這個(gè)標(biāo)簽可以查看值棧結(jié)構(gòu)和存儲(chǔ)值:
訪問action,執(zhí)行action的方法有返回值,配置返回到j(luò)sp頁面中,在jsp頁面中使用這個(gè)標(biāo)簽:
(3)action對(duì)象里面有值棧對(duì)象,值棧對(duì)象里面有action引用。
在action沒有做任何操作,棧頂元素默認(rèn)是action的引用。
?
4、向值棧放數(shù)據(jù)的三種方式:
(1)第一種:Set方法:HashMap類型(重新分配空間)
//向值棧放數(shù)據(jù)的三種方式: public class SaveStackDemoAction extends ActionSupport {public String execute(){//獲取ActionContext對(duì)象,調(diào)用方法獲取值棧對(duì)象ActionContext context=ActionContext.getContext();ValueStack stack=context.getValueStack();//第一種:set方法:stack.set("stackobject", "第一個(gè)對(duì)象");return "test"; } }(2)第二種:Push方法:String類型(重新分配空間):
//向值棧放數(shù)據(jù)的三種方式: public class SaveStackDemoAction extends ActionSupport {public String execute(){//獲取ActionContext對(duì)象,調(diào)用方法獲取值棧對(duì)象ActionContext context=ActionContext.getContext();ValueStack stack=context.getValueStack();//第二種:push方法:stack.push("第二個(gè)對(duì)象");return "test"; } }(3)第三種(常用):在action中定義常量,生成變量的get方法。(不用重新分配空間)
//向值棧放數(shù)據(jù)的三種方式: public class SaveStackDemoAction2 extends ActionSupport {//第三種方式://在action中定義變量,生成變量的get方法private String object;public String getObject() {return object;}public String execute(){object="第三個(gè)對(duì)象";return "test"; } }?
5、向值棧放對(duì)象:
實(shí)現(xiàn)步驟:
(1)第一步:在action中定義對(duì)象變量;
(2)第二步:生成變量的get方法;
(3)第三步:在執(zhí)行的方法里面,給對(duì)象設(shè)置值;
//向值棧放對(duì)象: public class SaveStackDemoAction3 extends ActionSupport {//在action中定義對(duì)象變量,生成對(duì)象的get方法private User user;public User getUser() {return user;}public String execute(){ //在執(zhí)行的方法里面,給對(duì)象設(shè)置值。user=new User();user.setUid(1);user.setUsername("張三");user.setPassword("123456");user.setAddress("中國");return "test"; } }?
6、向值棧放List集合:
實(shí)現(xiàn)步驟:
(1)第一步:在action中,定義list集合;
(2)第二步:生成list集合的get方法;
(3)第三步:在執(zhí)行的方法里面,給集合設(shè)置值。
//向值棧放list集合: public class SaveStackDemoAction4 extends ActionSupport {//在action中定義list集合,生成對(duì)象的get方法private List<User> list=new ArrayList<User>();public List<User> getList() {return list;}public String execute(){ //在執(zhí)行的方法里面,給list集合設(shè)置值。User user1=new User();user1.setUsername("張三");user1.setPassword("123456");user1.setAddress("中國");User user2=new User();user2.setUsername("李四");user2.setPassword("654321");user2.setAddress("北京"); list.add(user1);list.add(user2);return "test"; } }?
7、從值棧中獲取數(shù)據(jù):
使用struts2的標(biāo)簽+ognl表達(dá)式獲取值棧數(shù)據(jù):
<s:property value=”ognl表達(dá)式”/>
例子:獲取字符串;獲取對(duì)象;獲取list集合;取出set方法存取的數(shù)據(jù);取出push方法存取的數(shù)據(jù);
//在action中存放數(shù)據(jù): public class ReadStackDemoAction extends ActionSupport {//設(shè)置字符串private String username;public String getUsername() {return username;} //設(shè)置對(duì)象private User user=new User();public User getUser() {return user;} //設(shè)置list集合private List<User> list=new ArrayList<User>();public List<User> getList() {return list;}public String execute(){ username="這是一個(gè)字符串";user.setUsername("這是一個(gè)對(duì)象");user.setPassword("123456");user.setAddress("china");User user1=new User();User user2=new User();user1.setUsername("張三");user1.setPassword("123456");user1.setAddress("china");user2.setUsername("李四");user2.setPassword("123456");user2.setAddress("English");list.add(user1);list.add(user2);ActionContext context=ActionContext.getContext();ValueStack stack=context.getValueStack();//使用set方法存數(shù)據(jù):stack.set("set", "set方法存的數(shù)據(jù)");//使用push方法存數(shù)據(jù):stack.push("push方法存的數(shù)據(jù)");return "test";} } <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>案例</title> </head> <body><s:debug></s:debug><!-- 在jsp中獲取字符串 -->獲取值棧的字符串:<br/><s:property value="username"/><br/><br/>獲取值棧的對(duì)象:<br/><s:property value="user.name"/><s:property value="user.password"/><s:property value="user.address"/><br/><br/>獲取值棧的list集合:<br/>第一種方式:<br/><s:property value="list[0].name"/><s:property value="list[0].password"/><s:property value="list[0].address"/><br/><s:property value="list[1].name"/><s:property value="list[1].password"/><s:property value="list[1].address"/><br/><br/>第二種方式(常用):<br/><!-- 使用s:iterator:遍歷值棧的list集合 --><s:iterator value="list"><s:property value="name"/><s:property value="password"/><s:property value="address"/><br/></s:iterator><br/>第三種方式(最常用):<br/><s:iterator value="list" var="user"><!-- 遍歷值棧list集合,得到每個(gè)user對(duì)象機(jī)制:把每次遍歷出來的user對(duì)象放到context中獲取context里面數(shù)據(jù)的特點(diǎn):寫ognl表達(dá)式使用特殊符號(hào)# --><s:property value="#user.name"/><s:property value="#user.password"/><s:property value="#user.address"/><br/></s:iterator><br/><!-- 取出set方法存取的數(shù)據(jù),根據(jù)名稱獲取值 --><s:property value="set"/><br/><br/><!-- 取出push方法存取的數(shù)據(jù)--><!-- (1)使用push方法設(shè)置值,沒有名稱,只有設(shè)置的值(2)向值棧放數(shù)據(jù),會(huì)把向值棧放的數(shù)據(jù)存到數(shù)組里面,數(shù)值名稱為top,根據(jù)數(shù)據(jù)獲取值 --><s:property value="[0].top"/></body> </html>?
8、EL表達(dá)式怎么獲取值棧數(shù)據(jù):
(1)EL表達(dá)式獲取域?qū)ο笾?#xff1b;
(2)向域?qū)ο罄锩娣胖凳褂胹etAttribute方法,獲取值使用getAttribute方法。
(3)底層增強(qiáng)request對(duì)象里面的getAttribute方法:
--如果從request域獲取值,如果獲取到,則直接返回;
--如果從request域獲取不到值,到值域中把值獲取出來,把值放到域?qū)ο罄锩妗?/p>
9、#和%的使用:
(1)#的使用:獲取context里面的數(shù)據(jù);
(2)%的使用:在struts2標(biāo)簽里面使用ognl表達(dá)式,如果直接在struts2表單標(biāo)簽里面使用ognl表達(dá)式會(huì)發(fā)生不識(shí)別,只有在%之后才會(huì)識(shí)別。
?
?
三、攔截器:
1、struts2攔截器的介紹:
(1)struts2是框架,封裝了很多的功能,struts2里面封裝的功能很多都是在攔截器里面。
(2)struts2有很多攔截器,不是每次這些攔截器都執(zhí)行,每次執(zhí)行默認(rèn)的攔截器
(3)默認(rèn)攔截器的位置:struts2-core的jar包下面的struts-default.xml文件:
以下是默認(rèn)的攔截器:
<interceptor-stack name="defaultStack"><interceptor-ref name="exception"/><interceptor-ref name="alias"/><interceptor-ref name="servletConfig"/><interceptor-ref name="i18n"/><interceptor-ref name="prepare"/><interceptor-ref name="chain"/><interceptor-ref name="scopedModelDriven"/><interceptor-ref name="modelDriven"/><interceptor-ref name="fileUpload"/><interceptor-ref name="checkbox"/><interceptor-ref name="datetime"/><interceptor-ref name="multiselect"/><interceptor-ref name="staticParams"/><interceptor-ref name="actionMappingParams"/><interceptor-ref name="params"/><interceptor-ref name="conversionError"/><interceptor-ref name="validation"><param name="excludeMethods">input,back,cancel,browse</param></interceptor-ref><interceptor-ref name="workflow"><param name="excludeMethods">input,back,cancel,browse</param></interceptor-ref><interceptor-ref name="debugging"/><interceptor-ref name="deprecation"/></interceptor-stack>(4)攔截器在action對(duì)象創(chuàng)建之后,action的方法執(zhí)行之前執(zhí)行。
(5)攔截器底層使用兩個(gè)原理:
第一個(gè):aop思想:AOP是面向切面的編程,不改變?cè)创a,就可以增加功能;
第二個(gè):責(zé)任鏈模式;
(6)aop思想和責(zé)任鏈模式如何應(yīng)用到攔截器里面?
①攔截器在action對(duì)象創(chuàng)建之后,action的方法執(zhí)行之前執(zhí)行。
②在action方法執(zhí)行之前執(zhí)行默認(rèn)攔截器,執(zhí)行過程使用aop思想,在action沒有直接調(diào)用攔截器的方法,使用配置文件方式進(jìn)行操作。
③ 在執(zhí)行攔截器的時(shí)候,會(huì)執(zhí)行很多的攔截器,這個(gè)過程使用到責(zé)任鏈模式:
--假如執(zhí)行三個(gè)攔截器,執(zhí)行攔截器1,執(zhí)行攔截器1之后做放行操作,執(zhí)行攔截器2,執(zhí)行攔截器2之后做放行操作,執(zhí)行攔截器3,執(zhí)行攔截器3之后做放行,執(zhí)行action方法。
?
2、攔截器的執(zhí)行過程:
3、過濾器和攔截器的區(qū)別:
(1)過濾器:理論上可以攔截任意內(nèi)容,比如html,jsp,servlet,圖片路徑。
(2)攔截器:攔截器值攔截action。
4、servlet和action的區(qū)別:
(1)servlet:第一次訪問的時(shí)候創(chuàng)建,創(chuàng)建一次,單實(shí)例對(duì)象。
(2)action:每次訪問的時(shí)候都會(huì)創(chuàng)建,多實(shí)例對(duì)象。
?
5、自定義攔截器:
(1)首先,我們查看源代碼看攔截器的結(jié)構(gòu):
(2)在接口里面有三個(gè)方法:
void init();//初始化操作 void destroy();//銷毀操作 String intercept(ActionInvocation invocation);//攔截邏輯的操作(3)在實(shí)際開發(fā)中,建議使用另外一種方式開發(fā):
①創(chuàng)建類,繼承MethodFilterInterceptor類實(shí)現(xiàn);
②重寫里面的doIntercept方法,攔截器邏輯寫在方法體里面。
?
6、舉例:登陸攔截器:
(1)判斷是否登陸:判斷session里面是否有名稱是username的值;
(2)攔截器實(shí)現(xiàn)過程:
第一步:創(chuàng)建類,繼承MethodFilterInterceptor類;
第二步:重寫MethodFilterInceptor類里面的方法,方法里面寫攔截器邏輯;
//創(chuàng)建攔截器類:繼承MethodFilterInterceptor類 public class myIntercept extends MethodFilterInterceptor {//重寫里面的doIntercept方法,攔截器邏輯寫在方法體里面@Overrideprotected String doIntercept(ActionInvocation arg0) throws Exception {//取得username的值HttpServletRequest request=ServletActionContext.getRequest();Object obj=request.getSession().getAttribute("username");System.out.println(obj);if(obj!=null){//已經(jīng)登陸,攔截器做類似于放行的操作return arg0.invoke();}else{//沒有登陸,不執(zhí)行action里面的方法,返回登陸界面//回到result標(biāo)簽里面尋找到fail的值,到相應(yīng)的配置路徑中去return "fail";}} }第三步:注冊(cè)攔截器,配置action和攔截器的關(guān)系:
<!-- 登陸攔截器配置: --> <!-- 1.首先在package標(biāo)簽中聲明要使用的攔截器 --> <interceptors><interceptor name="logininterceptor" class="com.zwp.intercept.myIntercept"></interceptor> </interceptors><action name="customer_*" class="com.zwp.action.login.loginAction" method="{1}"><!-- 2.在action里使用自定義攔截器--><interceptor-ref name="logininterceptor"><!-- 配置action里面的某些方法不進(jìn)行攔截 :name:excludeMethods;值:action不攔截方法的名稱 --><param name="excludeMethods">login</param> </interceptor-ref><!-- 3.當(dāng)使用了自定義攔截器的時(shí)候,系統(tǒng)將不加載默認(rèn)攔截器,需要手動(dòng)配置一次 --><interceptor-ref name="defaultStack"></interceptor-ref><result name="success">/main.jsp</result><result name="fail">/login.jsp</result> </action>?
?
四、Struts2標(biāo)簽:
1、Struts2標(biāo)簽使用在jsp頁面中:
<s:property>:和ognl表達(dá)式在jsp頁面中獲取值棧數(shù)據(jù)
<s:iterator> :獲取值棧list集合數(shù)據(jù),表示list集合
<s:debug>:查看值棧結(jié)構(gòu)和數(shù)據(jù)。
2、常用的Html表單標(biāo)簽:
3、在struts2里面對(duì)應(yīng)的html表單標(biāo)簽大部分都有:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>struts常用表單標(biāo)簽</title> </head> <body><!-- 1.普通輸入域 --><s:textfield name="username" label="username"></s:textfield><br/><!-- 2.密碼輸入域 --><s:password name="password" label="password"></s:password><br/><!-- 3.單選框 --><!-- value和顯示值一樣 --><s:radio list="{'男','女'}" name="sex" label="性別"></s:radio><br/><!-- value和顯示值不一樣 --><s:radio list="#{'nan':'男','nv':'女'}" name="sex1" label="性別"></s:radio><!-- 4. 復(fù)選框--><s:checkboxlist list="{'java','android','jsp','lunix'}" name="hobit" lable="愛好"></s:checkboxlist><br/><!-- 5.下拉框 --><s:select list="{'初中','高中','大學(xué)','博士'}" name="college" label="學(xué)歷"></s:select><br/><!-- 6.文件上傳項(xiàng) --><s:file name="file" label="上傳文件"></s:file><br/><!-- 7.隱藏項(xiàng) --><s:hidden name="hide" value="abcd"></s:hidden><br/><!-- 8.文本域 --><s:textarea rows="10" cols="10" name="resume" label="簡歷"></s:textarea><br/><!-- 9.提交按鈕 --><s:submit value="提交"></s:submit><br/><!-- 10.重置按鈕 --><s:submit value="重置"></s:submit><br/></body> </html>?
?
五、Struts2實(shí)現(xiàn)文件上傳:
之前web階段實(shí)現(xiàn)上傳,使用組件FileUpload,使用struts2實(shí)現(xiàn)文件上傳,struts2對(duì)之前的FileUpload進(jìn)行封裝。
1、如何對(duì)上傳進(jìn)行封裝:
2、使用struts2框架方便實(shí)現(xiàn)文件上傳:
步驟:
(1)導(dǎo)入所需的jar包:
(2)頁面中的配置:
第一個(gè)要求:表單提交方式 post;
第二個(gè)要求:form標(biāo)簽里面有屬性 enctype屬性值,修改為 multipart/form-data
第三個(gè)要求:在表單里面有文件上傳項(xiàng),有name屬性 <input type=?“file” name=“”/>
(3)action中的配置:
①在action直接得到上傳文件名稱和上傳文件;
②在action定義成員變量,生成變量set和get方法;
(4)文件上傳的邏輯實(shí)現(xiàn):
①在具體的action的方法里面寫上傳邏輯;
②在服務(wù)器里面創(chuàng)建文件;
③把本地文件復(fù)制服務(wù)器文件里面;
(5)出現(xiàn)的問題:
①如果上傳的文件超過2M,出現(xiàn)異常:
②頁面中出現(xiàn)提示:沒有input結(jié)果定義:
(6)解決方法:在struts2.xml文件中配置:
①使用struts2做文件上傳大小默認(rèn)有限制的,默認(rèn)2M;
②可以設(shè)置允許上傳文件的大小:
--struts2里面有常量:
③頁面中Input處理:
input是struts2里面錯(cuò)誤處理機(jī)制,如果上傳文件超過設(shè)置的大小之后,自動(dòng)返回結(jié)果,結(jié)果名稱是input。
解決:配置input結(jié)果,到錯(cuò)誤頁面。
④當(dāng)struts2自動(dòng)返回input結(jié)果,出現(xiàn)錯(cuò)誤,在配置input的頁面中可以查看錯(cuò)誤信息。
--在配置的錯(cuò)誤頁面中,使用struts2標(biāo)簽可以查看到錯(cuò)誤的信息。
總結(jié)
以上是生活随笔為你收集整理的Struts2框架--学习笔记(下):OGNL表达式、值栈操作、拦截器、struts2标签、文件上传的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Struts2框架--学习笔记(上):搭
- 下一篇: Maven(一):安装与环境配置、使用M