Java框架的Struts2(六)

平、OGNL表达式语言

Ognl Object Graphic Navigation
Language(对象图导航语言),它是一致种功能强大的表达式语言(Expression
Language,简称为EL),通过她概括一致的表达式语法,可以存取对象的任意属性,调用对象的措施,遍历整个对象的构造图,实现字段类型转化等力量。

它们采取同一之表达式去存取对象的性质

Struts 2 默认的表达式语言是
OGNL,原因是它们相对其他表达式语言有下几乎特别优势:

1.支撑对象方法调用,如xxx.doSomeSpecial();

2.支撑类静态的法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名
| 值名],

例如:

@java.lang.String@format(‘foo %s’,
‘bar’)或@tutorial.MyConstant@APP_NAME;

3.支持赋值操作和表达式串联,如price=100, discount=0.8,
calculatePrice(price*discount),这个表达式会返回80;

4.访问OGNL上下文(OGNL context)和ActionContext;

5.操作集合对象。

6.可以一直new一个靶

OGNL 的施用场景

以标签中:

<s:property value="user.username" />  //这个 user.username 是个ognl表达式

布文件中

<result type="redirect"  > /main.jsp?name=${userName} </result>   //这里的 ${userName} 是ognl表达式

OGNL

顾属性

顾方法

访问静态属性或措施

走访构造函数

走访数组

走访集合

lambda  

老二、OGNL 应用举例

1) 属性获取

<s:property value="userName"/>  = ${userName}
<s:property value="user.userId"/>    //对象的某属性

漫山遍野属性  

<s:property value="user.schoolInfo.schoolName" />

2) 调用action中的静态方法

<s:property value="@cat.action.UserAction@getCountryName()" />
 /* 附: 必须要加入一个常量    
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />  才可以在ognl中调用静态方法
可以在  /org/apache/struts2/default.properties 中,查看到所有常量的值 */

3) 调用JDK 中类的静态方法

<s:property value="@java.lang.Math@floor(50.99)"/>

4) 调用价值栈中目标的屡见不鲜方法

<s:property value="user.testUser()"/> 

5) 调用寻常类中之静态属性

<s:property value="@cat.bean.UserInfo@country"/>

6) 调用构造方法

<s:property value="new cat.bean.UserInfo(100,'张三').userName"/> 

本例要于UserInfo 类中 增加一个构造函数

public UserInfo(int id,String userName){
          this.id=id;
          this.userName=userName;
          System.out.println("this is a dog");
}

7) 获取集合中的始末

假定值栈中产生一个ArrayList,里面放的凡 叫 userList ,里面的价值是
“aaa”,”bbb”,”ccc”则可以: <s:property value=”userList[0]”/> 得到
aaa

比方值栈中有一个 List<UserInfo>userList,则可坐数组的方式获得多少
<s:property value=”userList[0].userName”/>

8)  获取 map 中的值  

<s:property value="userMap['aaa'].userName"/>  //aaa 是个key

会合的伪属性

OGNL 能调用集合的有特别性能,它数属性并无是javaBean 模式之

主要有以下几独

size, isEmpty,

iterator

keys,values

next hasNext

nextElement,hasMoreElements

赢得 map 中具备的键<s:property value=”userMap.keys”/>

取 list 的长度 <s:property value=”userList.size”/>

三、ActionContext 和值栈   

Strut2中 OGNL Context 实现者为 ActionContext 它的组织如下

— ValueStack (值栈,是干净对象)

— parameters

— request

— session

— application

— attr

当 struts 接受一个伸手的下, 会迅速的创导 ActionContext, ValueStack,
Action, 然后拿 Action放到 ValueStack 中,Action 实例对象足以于 OGNL
访问。

注意:

当页面用OGNL设置值()这些访问的还是内外文中的这些目标的性)

<s:property value="#request.requestKey"/>  注意要用# 不用是访问不到的
<s:property value="#session.sessionKey"/> 

于是el表达式也会上平等的效力

${ requestKey}
${ sessionKey}    

parameters 的动场景

<result type="redirect">/b.jsp?name=1234455</result>  //注意如果这里不是redirect 方式,是取不到的
<s:property value=#attr.name / >

季、串并多只Action的值栈

1 写点儿个Action, A,和 B, 里面分别各自放少单不同名和字段,放一个同名的字段

public class A {
         private  String  a_userName;
         private String  a_password;
         private String xxx;

         public String execute(){
                  a_userName="张三";
                  a_password="sys123";
                  xxx="这是A里的xxx的值";
                  return "success";
              }
            }

         public class B {
             private String b_goodsName;
             private String b_goodsNo;
             private String xxx;

         public String execute(){
                b_goodsName="茶杯";
                b_goodsNo="009";
                xxx="这是b里xxx的值";
                return "success";    
            }

            <package name="packageOne" namespace="" extends="struts-default">
                <action name="a" class="cat.action.A">
                    <result type="chain">
                        <param name="actionName">b</param>
                    </result>
                </action>

                <action name="b" class="cat.action.B">
                    <result>/Main.jsp</result>
                </action>
            </package>

小心:当struts2接一个央的时,它见面快的创一个 上下文对象
ActionContex,然后创建 ValueStack,然后创建。

action,再将 action放到ValueStack中

action  已经放根对象中失去了,我们设拜访根对象吃的性能,是休欲#号的

五、使用ognl操作集合

使用ognl表达式创建 List/Map集合对象

<s:set> 标签用于将有值放入指定范围。它有以下简单单属性

scope:指定变量被放的限制,该属性可以领application、session、request、
page或action。如果没安装该属性,则默认放置在 OGNL Context 中。

value:赋给变量的值.如果没有设置该属性,则拿 ValueStack栈项的值赋给变量。

//例一:操作 List集合
            <s:set var="userList" value="{'黄世仁','邓世昌','李刚','杨达才'}" />
             ---//例一
                     s:iterator 标签在迭代时有一个特点,会把当前迭代的对象放在值栈的栈顶
                     <s:iterator value="#userList">
                              <s:property /> <br> //对于 s:property  如果不指定value 则value取值栈顶的值
                     </s:iterator>
             ---//例二
                     <s:iterator value="#userList" id="user">
                             <s:property  value="user" /> <br>  //这里指定了 property的 value 就是 上边的 id 
                                 ${user } //这里用El表达式也行
                     </s:iterator> 
               --- //例三 (处理声明时使用了scope 属性的集合)
                 <s:set var="userList" value="{'黄世仁','邓世昌','李刚','杨达才'}" scope="session" />
                    <s:iterator value="#session.userList" id="user" >
                             <s:property  value="user" /> <br> 
                            ${user }
                </s:iterator>

//例二:操作 Map 集合
             //注意,如果map中key对应的value是数字型,则可以不用''号
             <s:set var="userMap" value="#{'1号首长':'江','二号首长':'涛','三号首长':'平' }" />
             <s:iterator value="#userMap" >
                  <s:property value="key"/>=    <s:property value="value"/> <br>
             </s:iterator>

               对于集合类型,OGNL表达式可以使用in和not in两个元素符号判断元素是否在某个集合中=============
                <s:if test="'aaa' in {'aaa','bbb'}">
                  在
                  </s:if>
                  <s:else>
                       不在
                 </s:else>

               如果集合是个变量也可以
               <s:if test="'黄世仁' in #userList">
                    在
                  </s:if>
                  <s:else>
                       不在
                 </s:else>

六、ognl表达式的影功能

1 对项目增长数据库访问,然后于Action中,查出用户列表 userList 放在值栈里

2 UserManage.jsp 中

==全部取出

<s:iterator  value="userList">
<s:property value="userId"/>=<s:property value="userName"/><br>
</s:iterator>

==带投影的

?:获得有符合逻辑的素。

^:获得符合逻辑的率先独元素。

$:获得符合逻辑的末尾一个因素。

<s:iterator value="userList.{?#this.id>200}">
<s:property value="id"/>=<s:property value="userName"/><br>
</s:iterator>

==用jstl的

<c:forEach var="user" items="${userList}" >
${user.userId}     |     ${user.userName}    <br>
</c:forEach> 

七、struts 标签库概述

Struts2签分类

(1)UI标签:(User  Interface,
用户界面)标签,主要用于生成HTML元素标签,

UI标签而只是分为表单标签非表单标签

(2)非UI标签,主要用来数据访问,逻辑控制相当之竹签。非UI标签而分为流程控制标签

(包括用于落实分支、循环等工艺流程控制的签)和多少看标签(主要包括用户输出ValueStack中的价,完成国际化等力量的)

(3)ajax标签

==流程控制标签

if

elseif

else

append  //合并多只集到一个新集里

generator  //把字符串按某种标志进行切割成集合

iterator

merge   //合并多只聚众到一个新集里

sort

subset

==数据看标签

a

action

bean

date

debug

i18n

include

param

property

push

set

text

url

八、Struts2 数量访问标签

(一)<s:set>  标签  //设置值

<s:set var="dog" value="'安倍晋三'" /> 严重注意,dog 是要用单引号扩起来的, var 可以换写成name,但name被废弃了
//取值:
<s:property value="#dog"/> //可以
<s:property value="dog"/> //可以
${dog } //可以
<s:debug />

结过观察,发现而未指定scope, 它是身处 Stack Context (其实就算是context
map, Acton Context,OGNL Context,) 中之<hr/>

<c:set var=”num1″ value=”ooooooooo” scope=”request” />  这是jstl
标签

关于 scope :
               The scopes available are as follows :-
            application – the value will be set in application scope
according to servlet spec. using the name as its key
            session – the value will be set in session scope according
to servlet spec. using the name as key
            request – the value will be set in request scope according
to servlet spec. using the name as key
            page – the value will be set in page scope according to
servlet sepc. using the name as key
            action – the value will be set in the request scope and
Struts’ action context using the name as key    ‘

 

关于 set 的 参数
                Name     Required  Default Evaluated  Type      
Description
                id           false                      false        
String       Deprecated. Use ‘var’ instead  //Deprecated
这个单词是无挑成,反对的意思
                name     false                      false        
String       Deprecated. Use ‘var’ instead
                scope    false       action      false        
String      The scope in which to assign the variable. Can be
application, session, request, page, or action.
                value     false                      false        
String       The value that is assigned to the variable named name
                var        false                       false        
String       Name used to reference the value pushed into the Value
Stack
                     

2.<s:property> 标签 

用来出口表达式的值,如果指定value 属性,就输出value
对应之价值,如果没点名,它见面输出ValueStack 栈顶的价
1,访问Action值栈中的平凡属性:

<s:property value="attrName"/>  

2,访问Action值栈中的靶子属性(要有get set方法):

<s:property value="obj.attrName"/>
<s:property value="obj1.obj2.attrName"/> 

3,访问值栈中目标属性的计

<s:property value="obj.methodName()"/> 

4,访问值栈中action的平常方法:

 <s:property value="methodName()"/> 

5,访问静态方法:

<s:property value="@com.softeem.LoginAction@methodName()"/> 

6,访问静态属性:

配置属性文件,允许ognl访问静态方法struts.ognl.allow…=true

<s:property value="@com.softeem.LoginAction@attrName"/> 

7,访问Math类的静态方法:

<s:property value="@@min(9,7)"/> 

8,访问普通类的构造方法:

<s:property value="new com.softeem.User(2)"/> 

9,访问集合:

①list集合对象

<s:property value="listName"/> 

②list集合中的某个元素

<s:property value="listName[1]"/> 

③list中有属性的聚众

<s:property value="listName.{field}"/> 

④list中之一属性集合的特定值

<s:property value="listName.{field}[0]"/> 

⑤访问set

<s:property value="setName"/> 

⑥做客set中有元素

<s:property value="setName[0]"/> 

⑦访问map

<s:property value="mapName"/> 

⑧基于key访问Map中之要素

<s:property value="mapName.username"/>
<s:property value="mapName['username']"/>
<s:property value="mapName[/"username/"]"/> 

⑨访问map中所有的key

<s:property value="mapName.keys"/> 

10,访问map中所有的values

<s:property value="mapName.values"/> 

11,访问map的大小

<s:property value="mapName.size()"/> 

12,投影

<s:property value="listName.{?#this.age==1}"/>
<s:property value="listName.{^#this.age>1}"/>
<s:property value="listName.{$#this.age==1}"/>
<s:property value="listName.{$#this.age==1}.{age}==null"/>
[]:<s:property value="[0]"/>值栈中的对象 

default:可选属性,如果欲输出的属性值为null,则显得该属性指定的值

escape:可选属性,指定是否格式化HTML代码,不搭荐,应该据此escapeHtml

value:可选属性,指定要输出的属于性值,如果没有点名该属性,则默认输出ValueStack栈顶的值。

id:可选属性,指定该因素的标识 这个特性好象在新本子被一度没了

        Name                   Required   Default         
 Evaluated     Type     Description
                default             false                           
false                String      The default value to be used if value
attribute is null
        //    escape              false        true                 
false                Boolean      Deprecated. Use ‘escapeHtml’.
Whether to escape HTML
                escapeCsv            false        false              
      false                Boolean      Whether to escape CSV (useful
to escape a value for a column)
                escapeHtml          false       true               
      false                Boolean      Whether to escape HTML
                escapeJavaScript    false        false              
      false                Boolean      Whether to escape Javascript
                escapeXml            false        false              
      false                Boolean      Whether to escape XML
                value                false        <top of stack>
false                Object      Value to be displayed

//例子:
<s:set var="userName" value="'struts标签真烂'"  />  严重注意, 里面要有单引号
<s:property value="#userName" /> //正常该加 # 
<s:property value="userName" />  //不加也能取出来
<c:out value="${userName}"></c:out> //用jstl标签也能取

上边的效益全好就此 jstl标签取代 如下:

<c:set var="userMsg" value="struts 标签库的设计者是白痴" />
${userMsg}
<c:out value="${cat_name}" default  ="--------------------"/>

(二)<s:action> 标签

大凡故来调用Action的价签,在JSP中页面被,可以切实指定某个平命名空间被的某部同Action。而标签的重心用于展示与渲染Actionr的处理结果。

action标签有如下几个特性:

1、id:  可选,作为该action的引用ID //作废

2、name:  必填,调用action的名字

3、namespace:  可选,action所在的nqmespace

4、executeResult,可选取,指定是否拿action的处理结果页面包含到本页面。

5、ignoreContextParame:  可卜,指定该页面的求参数是否要传入action.

6、var

7、rethrowException

8、flush

//这个userAction的名字,是给本页面中别的标签引用用的,
          <s:action name="listUser" var="page_userAction" executeResult="false"> 如果把executeResult换成true则会把result对应的视图传过来
                <s:param name="paramAAA">调Action时传一个参数</s:param> 可以通过这种方法给被调用的action传参数,在action中可以用值栈的方式取到它
            </s:action>

            <s:iterator value="#userAction.userList"> 可以这样取出被调用的action中的值,注意,这些值是放在 StackContext中的,所以要加#
                <s:property value="userName" />
            </s:iterator>

            <c:forEach var="user" items="${page_userAction.userList}"> 使用jstl 标签,把传过来的值生成一组复选框
                 ${user.userName}: <input type="checkbox" value='${user.userId}' />
          </c:forEach>

            <s:debug />

== <s:push> 把表达式的值放入valueStack 的栈顶
== <s:url> 标签

<s:url action="UserAction" namespace="/test">
<s:param name="userId" value="10"/>
<s:param name="userName" value="'赵铁冷'"/> 需要注意: 如果value是汉字,早要加单引号 ,如果是中文,会被url编码
</s:url>

//实例: 访问UserAction 
<a href='<s:url action="UserAction" namespace=""> //UserAction是配置在xml文件中的名字
   <s:param name="userId" value="10"/>
   <s:param name="userName" value="'赵铁冷'"/>
</s:url>'
> 去Action里串串门 </a>

知识点回顾: 在UserAction中取出 userName

可于UserAction 中定义一个 userName
字段,生成get和set方法,这是前方常用之
struts取请求参数的法子。硬生生的抱request对象,从requet中获取,这是先前常用之点子,如下:

 HttpServletRequest request=ServletActionContext.getRequest();
                String tempStr=request.getParameter("userName");
                tempStr=new String(userName.getBytes("ISO8859-1"),"UTF-8");
            String userName=URLDecoder.decode(tempStr,"UTF-8"); //其实在这个地方不decode也行
          //打印 userName 

         <s:set name="myurl" value="'http://www.baidu.com'"/>
             <s:url value="#myurl" />
         <s:url value="%{#myurl}" />  //它的value默认接收的是字符串,而不是ognl表达式,如果想用表达式得转一下

九、Struts2 流程控制标签

==iterator标签

她的参数,还有 begin 和 end 从第几个因素开始,迭代几单 begin =”2″
end=”4″,用于对聚集进行迭代,这里的聚众包含List、Set和数组。

<s:set name="list" value="{'西瓜','哈密瓜','大傻瓜','半拉瓜'}" />
            <s:iterator value="#list" var="瓜名" status="st">  //这里的var 也可以用 id,但id 不推荐
                <font color= 
                           <s:if test="#st.odd">red</s:if>
                           <s:else>blue</s:else>
                         >
                       <s:property value="瓜名"/>
                    count:     <s:property value="#st.getCount()" />
                    index:     <s:property value="#st.getIndex()" />
                </font><br>
            </s:iterator> 

== if else

 <s:set var="广告名" value="'脑白金'" />

            <s:if test="#广告名=='脑白金'"> //注意,这里不用 #可就不行了
                脑残广告,傻子才买
            </s:if>
            <s:elseif test="#广告名=='梦酒'">
                五粮醇风,古方秘制,钦誉中外,独占鳌头
            </s:elseif>
            <s:else>
                说不定是就锅王胡师傅
         </s:else> 

可就此jstl代替上边的效应:

<c:choose>
            <c:when test="${广告名=='梦酒'}"> 一看就想喝的梦酒</c:when>
            <c:when test="${广告名=='脑白金'}">让人想吐的脑白金</c:when>
            <c:otherwise>估计十有八九是锅王胡师傅</c:otherwise>
</c:choose>

//对于上例,可以指定 scope
            <s:set name="广告名" value="'脑白金'"  scope="request"/> 指定泛围为 request 
            <s:if test="#request.广告名=='脑白金'"> 取的时候也要用 request.
                脑残广告,傻子才买
            </s:if>
            <s:elseif test="#request.广告名=='梦酒'">
                五粮醇风,古方秘制,钦誉中外,独占鳌头
            </s:elseif>
            <s:else>
                说不定是就锅王胡师傅
            </s:else> 

十、Struts2 UI标签

== 主题以及模板 

Struts2提供了三种主题,ajax, simple,
css_xhtml,xhtml,它默认的凡xhtml主题,开发时我们一般都选simple。因为Struts2怀有的UI标签还是冲主题与模板的,主题与模板是Struts2所起UI标签的主干。模板是一个UI标签的外在表示形式,例如:当我们运用<s:select
… …
/>标签时,Struts2即使见面根据对应select模板来十分成一个发模板特色的下拉列表框。如果为所有的UI标签都提供了相应的沙盘,那么就一系列之模版就形成了一个主题。

对一个JSP页面里富含的UI标签而言,即可以直接装该UI标签需要运用的模板,也可以安装该UI标签下的主题。实际上对开发者而言,并无推荐直接设置模板属性,而是应该选特定主题。设置主题的法子来以下几栽:

1,通过设定特定UI标签及之theme属性来指定主题。

2,通过设定特定UI标签外围之Form标签的theme属性来指定主题。

3,通过获取page\request\session\application
会话范围外为theme为名称的习性来确定主题。

4,通过取得名为也struts.ui.theme的常量(默认值是xhtml)来确定主题,该常量可以于struts.properties文件或者struts.xml文件被规定。如:

<constantname="struts.ui.theme" value="simple" />

==表单标签

1 <s:checkboxlist>

====如果凑为list

<s:checkboxlist name="list" list="{'Java','.Net','RoR','PHP'}" value="{'Java','.Net'}"/>

转如下html代码:

<input type="checkbox" name="list" value="Java" checked="checked"/><label>Java</label>
<input type="checkbox" name="list" value=".Net" checked="checked"/><label>.Net</label>
<input type="checkbox" name="list" value="RoR"/><label>RoR</label>
<input type="checkbox" name="list" value="PHP"/><label>PHP</label>

其默认会生成有主题相关的tr td等,如果不思量如果,可以于struts.xml中配置 
<constant name=”struts.ui.theme” value=”simple” />

====如果凑为MAP

<s:checkboxlist name="map" list="#{1:'瑜珈用品',2:'户外用品',3:'球类',4:'自行车'}" listKey="key" listValue="value" value="{1,2,3}"/>

变更如下html代码:

<input type="checkbox" name="map" value="1" checked="checked"/><label>瑜珈用品</label>
<input type="checkbox" name="map" value="2" checked="checked"/><label>户外用品</label>
<input type="checkbox" name="map" value="3" checked="checked"/><label>球类</label>
<input type="checkbox" name="map" value="4"/><label>自行车</label>

====如果凑是里放的凡javaBean

 <%
                          Person person1 = new Person(1,"第一个");
                          Person person2 = new Person(2,"第二个");
                          List<Person> list = new ArrayList<Person>();
                          list.add(person1);
                          list.add(person2);
                          request.setAttribute("persons",list);
                          %>
                        <s:checkboxlist name="beans" list="#request.persons" listKey="personid" listValue="name"/>

Personid和name为Person的属性

扭转如下html代码:

<input type="checkbox" name=“beans" value="1"/><label>第一个</label>
<input type="checkbox" name=“beans" value="2"/><label>第二个</label>

事例:在 UserManage.jsp 中
(因为前面已经召开了列有用户的例子,所以现在足一直获取内容)

<s:checkboxlist name=”beans” list=”userList” listKey=”id”
listValue=”userName”/>然后 访问
http://localhost:8080/OGNL/UserAction!getAllUser

2 <s:radio>

欠标签的以与checkboxlist复选框相同。如果凑里存放的凡javabean(personid和name为Person的属性)

 <s:checkboxlist name="beans" list="#request.persons" listKey="personid" listValue="name"/>

变迁如下html代码:

<input type="radio" name="beans" id="beans1" value="1"/><label>第一个</label>
<input type="radio" name="beans" id="beans2" value="2"/><label>第二个</label>

假若凑为MAP

<s:radio name="map" list="#{1:'瑜珈用品',2:'户外用品',3:'球类',4:'自行车'}" listKey="key" listValue="value“ value="1"/>

扭转如下html代码:

<input type="radio" name="map" id="map1" value="1"/><label for="map1">瑜珈用品</label>
<input type="radio" name="map" id="map2" value="2"/><label for="map2">户外用品</label>
<input type="radio" name="map" id="map3" value="3"/><label for="map3">球类</label>
<input type="radio" name="map" id="map4" value="4"/><label for="map4">自行车</label>

倘若凑为list

<s:radio name="list" list="{'Java','.Net'}" value="'Java'"/>

转如下html代码:

<input type="radio" name="list" checked="checked" value="Java"/><label>Java</label>
<input type="radio" name="list" value=".Net"/><label>.Net</label>

十一、<s:token > 用来防护表单重复提交

事例:重复提交的例子

1.

private UserInfo userInfo;
        public String add(){        
            UserDao dao=new UserDao();
          dao.addUser(this.userInfo);
                return "success";

}

2 struts.xml中 配置Action

<action name="UserAction_Add" class="cat.action.UserAction" method="add">
       <result name="success">/Succ.jsp</result>
</action>

 3 UserAdd.jsp中

<s:form action="UserAction_Add" namespace="" method="post">
     姓名:<s:textfield name="userInfo.userName" />
     账号:<s:textfield name="userInfo.userId" />
     密码:<s:password name="userInfo.password" />
     备注:<s:textarea name="userInfo.note" />
<s:submit value="提交" />
</s:form>

4 进行提交,看刷新后的更提交的结果

用 tokey 标签防止重复提交,用法如下:

1 在表单中入<s:token />

<s:token/>  //加入这个tokey

….

2 在XML中

<action name="UserAction_Add" class="pinkcat.action.UserAction" method="add">
         <interceptor-ref name="defaultStack"/>   //注意,默认的拦截器栈一定要加上
         <interceptor-ref name="token"/>
         <result name="invalid.token">/UserAdd.jsp</result>   //设置用户如果重复提交,则返回添加页
<result name="success">/Succ.jsp</result>

3 在UserAction 中 让该继承自 extends ActionSupport

十一、拦截器

Interceptor

暨过滤器很形象,但她只有捕获 Action。在Struts2 中
许多Action通常还发局部联机需要关怀的题材,比如来一部分Action
它们还需针对页面上之输入进行校验,有一些Action需要针对上传的文本进行一下先行处理,还有有Action可能需要防表单的又提交
(double submit)
还有为数不少Action需要在页面显示之前用下拉列表和其它一些控件事先假装好价,通过拦截器策略,Struts2
框架让共享这些题目还易。

拦截器能当 Action 被调用之前与为调用之后执行有 “代码”,Struts2
框架的大多数效都是透过拦截器来促成的,如防止再次提交,类型转换,对象封装,校验,文件上传,页面装载等等。每一个拦截器都是独立装载的(pluggable)
,可以因实际的得也各级一个Action 配置需要因此的掣肘器. 例如: 一个Action
需要动用类型转换器 和 文件上传,那么我们得以给其装两独拦截器。

拦截器是Struts2
框架的骨干,包括分析呼吁参数,将请求参数赋值给Action属性,执行多少校验,文件上传等工作且是用其实现之Struts2规划之灵巧性,更多的受益与拦截器的设计.当需要展开扩张时,只待提供相应的拦截器,并以其配置于Struts2容器中即可,反的可采摘 
(AOP) 面向切面。

十二、struts2 自带的拦截器

Struts2 内建了大气拦截器,它们 以 name-class 对的花样布置当
struts-defalut.xml 文件被

alias: 实现在差请示着貌似参数别外的更换

autowiring 自动装配的拦截器,用于和Spring 进行整治并

chain 构建一个Action链,使目前的Action可以看前一个Action的性能 一般与
<result type=”cahin”> 一起使用

conversionError 处理类型转换错误 它承担用类型转换错误从ActionContext
中取出,并转移成Action 的FieldError 错误

createSession 负责创建一个HttpSession对象

debugging 当使用Struts2 支付模式时,它见面交到更多之调试信息

execAndWait 后台执行Action,负责用等画面发送给用户

execption 处理非常,将死映射为结果 

fileupload 文件上传,解析表单域中的内容

i18n 国际化,负责管所选取语言,区域放入用户Session中

ogger 日志记录,主要是输出Action 的名

model-driven 一个用于模型驱动之拦截器, 当某个Action 类实现了
ModeDriven接口时,它承受把getModel() 方法的结果堆入ValueStack中

scope-model-driven

params
最中心的一个拦截器,负责解析Http请示着之参数,并拿参数值设置成Action对应的属于性值

prepare 如果Action实现了Prepareable 接口,会调用访栏截器中之prepare()方法

static – params
将XML中<action>标签下的<param>标签中之参数传入 Action

scope 范围转换 可以将Action 状态信息保存及 HttpSession 或 ServletContext
范围外

servlet-config 如果有Action 需要直接看 Servlet Api
,则通过它们实现(尽量避免在Action中直接访问Servlet Api,高耦合)

roles JAAS java权限同说明服务 拦截器,有且才会调用该拦截器拦截的Action

timer 输出Action执行时 分析Action性能的瓶颈时有用

token 阻止重复提交

token -session 和方面相似,只是将token保存于HttpSesison中

validation
通过履行于xxxAction-validation.xml中定义之校验器.从而形成多少校验

workflow 负再调用 Action类中之 validation 方法,如失败则归 Input视图

十三、自定义拦截器    

于定义拦截器有三栽方法

1) 实现 Interceptor 接口

2) 继承自 AbstractInterceptor

3) 继承自 MethodFilterInterceptor 

规章一 计算一个Action的实行时间之拦截器,继承自 AbstractInterceptor方式贯彻

1) 定义一个阻拦器类

public class MyInterceptor extends AbstractInterceptor {

                //这个String 代表执行完Action后的返回值
                public String intercept(ActionInvocation invocation) throws Exception {
                    System.out.println("拦截开始");
                    long begintime=System.currentTimeMillis();

                    String result=invocation.invoke(); //执行A    ction中的对应的方法

                    long endtime=System.currentTimeMillis();
                    System.out.println("该action 共执行了:"+(endtime-begintime)+" ms");

                    System.out.println("拦截结束");

                    return result;
                }
            }

关于 ActionInvocation   

ActionInvocation就是Action的调用者。ActionInvocation在Action的尽过程被,负责Interceptor、Action和Result等一样多元元素的调度。Interceptor通过ActionInvocation可以了的变更
Action行为:不让其执行、改变返回值、甚至可细颗粒的操作Action的道。它起getActionProxy(),getResultCode();getInvocationContext();getAction()
等办法。比如 可以经过 getAction 拿到Action对象,并尽中的不二法门:

MoreMethodAction M=(MoreMethodAction)invocation.getAction();
                 M.test(); 

要么经过她将到 ActionContext 对象

ActionContext act=invocation.getInvocationContext();

2) 在部署文件被布局

<package name="packageOne" extends="struts-default" >
         <interceptors>
         <interceptor name="myInte_AAA" class="cat.interceptor.MyInterceptor" />
         </interceptors>
         <action name="userAction_*" class="cat.action.UesrAction" method="{1}" >
                    <result name="success">/main.jsp</result>
                    <interceptor-ref name="myInte_AAA" />
                    <interceptor-ref name="defaultStack" />      //如果引入了自定义的拦截器,系统就不再提供默认的拦截器栈了,所以要自己手功引入
         </action>
</package>

3) action

public class UesrAction {
                        public String add(){
                            System.out.println("add 方法被调用了");
                            return "success";
                        }

                        public String del(){
                            System.out.println("del 方法被调用了");
                            return "success";
                        }
                        public String update(){
                            System.out.println("update 方法被调用了");
                            return "success";    
                        }
                        public String search(){
                            System.out.println("search 方法被调用了");
                            return "success";    
                        }
                    }

章二 灵活的限拦截哪些措施,不遮哪些措施= //通过连续
MethodFilterInterceptor 方式实现

1) 拦截器

public class MyInterceptor2  extends MethodFilterInterceptor{
                protected String doIntercept(ActionInvocation invocation) throws Exception {
                    System.out.println("MethodFilterInterceptor 启动");
                    String result=invocation.invoke();    
                    System.out.println("MethodFilterInterceptor 结束");
                    return result;
                }    
            }

2) 配置文件

<package name="packageOne" extends="struts-default" >
                <interceptors>
                    <interceptor name="myInte_AAA" class="cat.interceptor.MyInterceptor" />
                    <interceptor name="myInte_BBB" class="cat.interceptor.MyInterceptor2" >  //这是针对  MyInterceptor2 的
                        <param name="excludeMethods">search,update,del</param> //这里的面的方法,不会被拦截
                    </interceptor>
                </interceptors>
                <action name="userAction_*" class="cat.action.UesrAction" method="{1}" >
                    <result name="success">/main.jsp</result>
                    <interceptor-ref name="myInte_AAA" />
                    <interceptor-ref name="myInte_BBB" />  //引用声明的拦截器
                    <interceptor-ref name="defaultStack" />    
                </action>
</package>

3) action 同上例一样,略

访问 userAction_add,userAction_del 等艺术,可以窥见, <param
name=”excludeMethods”>search,update,del</param>
中宣称的当即几只法子没有给阻挡。

把: 使用拦截器栈

<package name="packageOne" extends="struts-default" >
                        <interceptors>
                            <interceptor name="myInte_AAA" class="cat.interceptor.MyInterceptor" />
                            <interceptor name="myInte_BBB" class="cat.interceptor.MyInterceptor2" >
                                <param name="excludeMethods">search,update,del</param>
                            </interceptor>

                            <interceptor-stack name="myStack">   //将自己声明的两个拦截器和系统的 defaultStack 组成一个拦截器栈
                                <interceptor-ref name="myInte_BBB" />
                                <interceptor-ref name="myInte_AAA" />
                                <interceptor-ref name="defaultStack" />
                            </interceptor-stack>
                        </interceptors>

                        <action name="userAction_*" class="cat.action.UesrAction" method="{1}" >
                            <result name="success">/main.jsp</result>
                            <interceptor-ref name="myStack" />  //引用拦截器栈
                        </action>
                    </package>

规章三 系统拦截器的调用,登录延时提醒ExecuteAndWaitInterceptor
很适合当后台长时运作的action时,它可以只是也用户一个温馨之守候界面,例如进度漫漫。

无以默认的 defaultStack 中
1)

<action name="loginAction" class="cat.action.UesrAction" method="login">
                    <result name="success">/main.jsp</result>
                    <result name="wait" >/wait.jsp</result>
                    <interceptor-ref name="defaultStack"></interceptor-ref>
                    <interceptor-ref name="execAndWait">
                        <param name="delay">2000</param>
                    </interceptor-ref>
          </action>

2) wait.jsp 中

<meta http-equiv="refresh" content="1;URL=loginAction" >
//或
response.setHeader("refresh", "3;URL=loginAction");

3) 在loginAction 设置 Thread.sleep(4000)

本例说明:

当调用 loginAction 的上,程序会因 配置文件被 delay 属性( 2000
)等待Action先实施 2000 毫秒, 但由于Action 中 sleep(4000),
所以它没有执行了,这时拦截器就将要发到 wait 视图上去了,wait
视图中每隔一秒 访问一下 loginAction,但这时loginAction对应之非常
Action还于酣睡着,所以看为是无用的,(这些请求都被忽略了?) 直到其苏醒,
这时刷过去的乞求虽径直到result上了。

例四 Session 权限拦截器

 

public class SessionInterceptor  extends MethodFilterInterceptor{

                @Override
                protected String doIntercept(ActionInvocation invocation) throws Exception {
                    //方式一 (取到sesssion中的内容)
                    /*ActionContext ctx=ActionContext.getContext();
                    ctx.getSession()*/

                    //方式二
                    //ServletActionContext.getRequest().getSession();

                    //方式三
                    UserInfo user=(UserInfo)invocation.getInvocationContext().getSession().get("userInfo");

                    if(user!=null){
                        return invocation.invoke();
                    }
                    else{
                        System.out.println("没有登录");
                        ActionContext.getContext().put("msg","您还没有登录");
                        return "no_login";
                    }            
                } 
            }


        <interceptor name="session_Inte" class="cat.interceptor.SessionInterceptor" >
                <param name="excludeMethods">login</param>
        </interceptor>
              ... 

      <action name="sessionAction_*" class="cat.action.UesrAction" method="{1}" >
            <result name="success">/main.jsp</result>
            <interceptor-ref name="session_Inte" />
            <interceptor-ref name="defaultStack" />
        </action>

十四、在struts2中使用Ajax

(通过 stream 类型的 result 实现)

public class AjaxAction {
            private String userName;
            private String result;
             ... get  set 方法

            public String checkUser(){
                if("admin".equals(userName)){
                    result="用户名已经被别人使用";
                    return "success"; 
                }
                else{
                    result="用户名可用";    
                    return "success"; 
                }    
            }

            //把字符串转成  ByteArrayInputStream
            public InputStream getInputStream() throws UnsupportedEncodingException {
                return new ByteArrayInputStream(result.getBytes("utf-8"));
            }

页面: ajax_test.jsp

$(function() {
                $("#btn1").click(function(){
                    $.ajax({
                        url:"ajaxAction_checkUser",
                        data:{userName:"admin"},
                        type:"post",
                        success:function(data){
                            $("#divResult").html(data);
                        }
                    });
                });
            });

        //或  $("#div2").load("ajaxAction_checkUser",{userName:"admin"});  //这样写更简单

        <package name="packageTwo" extends="struts-default" >
            <action name="ajaxAction_*" class="cat.action.AjaxAction" method="{1}">
                <result type="stream" >
                    <param name="contentType">text/html</param>
                    <param name="inputName">InputStream</param>
                </result>
            </action>
        </package>

十五、在struts2中使用Ajax

(通过 json 插件实现)

 

    //页面 
      $("#btn2").click(function(){
             $.ajax({
                url:"ajaxAction2_getAllUser",
                type:"post",
                dataType:"json",
                success:function(userList){
                    $.each(userList,function(key,user){
                        var trStr="<tr><td>"+user.id+"</td><td>"+user.userName+"</td><td>"+user.password+"</td></tr>";
                        $("#table1").append(trStr); 
                    }); 
                }
            }); 


     //Action 
            public class AjaxAction2 {
                private String userName;
                private String result;
                List<UserInfo> userList;

                public String getAllUser(){
                    userList=new UserDao().getAllUser();
                    return "success"; 
                }

    //配置文件 
            <package name="packageThree" extends="json-default" >
                <action name="ajaxAction2_*" class="cat.action.AjaxAction2" method="{1}">
                    <result name="success" type="json" >
                    <param name="root">userList</param>
                </action>
            </package>

外加说明:

一旦以地方的 action 中莫指定     <param
name=”root”>userList</param> 这个选项,则它会管所有action
对象做吗json 数据返回,如果这么,前而取数据的主意如下:

$("#btn2").click(function(){
             $.ajax({
                url:"ajaxAction2_getAllUser",
                type:"post",
                dataType:"json",
                success:function(action){
                  var userList=action.userList;  //因为返回的是整个action 所以这里要这样取出
                     console.info(userList);
                    $.each(userList,function(key,user){

                        var trStr="<tr><td>"+user.id+"</td><td>"+user.userName+"</td><td>"+user.password+"</td></tr>";
                        $("#table1").append(trStr); 
                    }); 
                }
}); 

       

 

相关文章