Java框架之Struts二(6)

一、OGNL表明式语言

Ognl Object Graphic Navigation
Language(对象图导航语言),它是一种成效强大的表明式语言(Expression
Language,简称为EL),通过它大约一致的表明式语法,能够存取对象的任意属性,调用对象的措施,遍历整个对象的布局图,完毕字段类型转化等效能。

它应用同一的表明式去存取对象的个性

Struts 2 私下认可的表达式语言是
OGNL,原因是它相对别的表明式语言具有上边几大优势:

一.帮衬对象方法调用,如xxx.doSomeSpecial();

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

例如:

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

叁.支撑赋值操作和表明式串联,如price=100, discount=0.捌,
calculatePrice(price*discount),这些表明式会回去80;

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

5.操作集合对象。

陆.足以直接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" />

贰) 调用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)"/>

四) 调用值栈中指标的常见方法

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

5) 调用普通类中的静态属性

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

陆) 调用构造方法

<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");
}

七) 获取集合中的内容

一经值栈中有一个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 和值栈   

Strut第22中学 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的值栈

一 写八个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>

小心:当struts贰接受四个呼吁的时候,它会火速的创始八个 上下文对象
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> 

7、struts 标签库概述

Struts二标签分类

(一)UI标签:(User  Interface,
用户界面)标签,首要用来生成HTML成分标签,

UI标签又可分为表单标签非表单标签

(二)非UI标签,首要用于数据访问,逻辑控制等的价签。非UI标签可分为流程序控制制标签

(包罗用于落到实处分支、循环等流程序控制制的标签)和数量访问标签(首要回顾用户输出ValueStack中的值,落成国际化等成效的)

(3)ajax标签

==流程序控制制标签

if

elseif

else

append  //合并八个汇聚到1个新集合里

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

iterator

merge   //合并七个聚众到3个新集合里

sort

subset

==数据访问标签

a

action

bean

date

debug

i18n

include

param

property

push

set

text

url

八、Struts贰 数额访问标签

(一)<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 栈顶的值
一,访问Action值栈中的普通属性:

<s:property value="attrName"/>  

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

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

三,访问值栈中目的属性的点子

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

四,访问值栈中action的常见方法:

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

5,访问静态方法:

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

六,访问静态属性:

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

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

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

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

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

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

九,访问集合:

1list集合指标

<s:property value="listName"/> 

二list集合中的某部成分

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

3list中某些属性的集合

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

4list中有些属性集合的特定值

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

⑤访问set

<s:property value="setName"/> 

6访问set中有些成分

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

⑦访问map

<s:property value="mapName"/> 

8基于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中页面中,能够切切实实内定某一命名空间中的某1Action。而标签的关键性用于展示及渲染Actionr的处理结果。

action标签有如下多少个性格:

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

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

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

四、executeResult,可选,钦点是不是将action的处理结果页面包含到本页面。

五、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表达式,如果想用表达式得转一下

九、Struts二 流程序控制制标签

==iterator标签

它的参数,还有 begin 和 end 从第多少个因素伊始,迭代多少个 begin =”2″
end=”四”,用于对聚集进行迭代,那里的联谊包罗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标签

== 主题和模板 

Struts贰提供了二种核心,ajax, simple,
css_xhtml,xhtml,它暗中认可的是xhtml核心,开发时大家一般都选simple。因为Struts二有着的UI标签都以基于宗旨和模板的,大旨和模板是Struts2全数UI标签的基本。模板是3个UI标签的外在表示方式,例如:当大家采用<s:select
… …
/>标签时,Struts二就会依据对应select模板来生成三个有模板特色的下拉列表框。借使为所有的UI标签都提供了相应的模版,那么那多重的模板就形成了一个大旨。

对此贰个JSP页面里带有的UI标签而言,即能够直接设置该UI标签必要选拔的模版,也足以安装该UI标签使用的核心。实际上对开发者而言,并不引进直接设置模板属性,而是应该接纳特定核心。设置大旨的艺术有以下两种:

一,通过设定特定UI标签上的theme属性来钦命宗旨。

二,通过设定特定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>

它暗中认可会生成1些宗旨相关的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>

1旦集合为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>

10一、<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>

四 举办付出,看刷新后的重新提交的结果

行使 tokey 标签防止再度提交,用法如下:

一 在表单中加入<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>

叁 在UserAction 中 让其继承自 extends ActionSupport

十一、拦截器

Interceptor

和过滤器很象,但它只捕获 Action。在Struts二 中
许多Action日常都有1些联合举行供给关切的题材,比如有部分Action
它们都急需对页面上的输入进行校验,有一部分Action须求对上传的公文进行一下预处理,还有一对Action恐怕需求幸免表单的双重提交
(double submit)
还有好多Action须求在页面展现在此以前将下拉列表和别的一些控件事先装好值,通过拦截器策略,Struts贰框架使得共享那几个标题更易于。

拦截器能在 Action 被调用之前和被调用之后执行一些 “代码”,Struts二框架的超过一半效能都以透过拦截器来贯彻的,如制止重复提交,类型转换,对象封装,校验,文件上传,页面装载等等。每多个拦截器都以独自装载的(pluggable)
,能够根据实际的内需为每一个Action 配置须要用的阻拦器. 例如: 二个Action
要求用到类型转换器 和 文件上传,那么大家能够给它设置七个拦截器。

拦截器是Struts2框架的基本,包蕴分析呼吁参数,将请求参数赋值给Action属性,执行多元帅验,文件上传等工作都以用它完成的Struts二统一筹划的灵巧性,更多的收益与拦截器的设计.当须求开展扩展时,只要求提供对应的拦截器,并将它配备在Struts贰容器中即可,反之能够采摘 
(AOP) 面向切面。

10二、struts二 自带的拦截器

Struts2 内建了大批量拦截器,它们 以 name-class 对的花样布署在
struts-defalut.xml 文件中

alias: 达成在分歧请示中貌似参数别外的转移

autowiring 自动装配的拦截器,用于和Spring 实行整合

chain 创设二个Action链,使当前的Action能够访问前一个Action的属性 一般和
<result type=”cahin”> 1起使用

conversionError 处理类型转换错误 它承受将类型转换错误从ActionContext
中取出,并转换来Action 的FieldError 错误

createSession 负责创制一个HttpSession对象

debugging 当使用Struts贰 支付方式时,它会提交越多的调节和测试音讯

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

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

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

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

ogger 日志记录,首若是输出Action 的名字

model-driven 八个用来模型驱动的拦截器, 当某些Action 类达成了
ModeDriven接口时,它担负把getModel() 方法的结果堆入ValueStack中

scope-model-driven

params
最主旨的3个拦截器,负责解析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视图

10叁、自定义拦截器    

自定义拦截器有三种方法

1) 实现 Interceptor 接口

2) 继承自 AbstractInterceptor

3) 继承自 MethodFilterInterceptor 

例1 总计2个Action的实践时间的拦截器,继承自 AbstractInterceptor形式贯彻

一) 定义二个阻碍器类

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();

贰) 在布置文件中布署

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

三) action 同上例1样,略

访问 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 属性( 两千)等待Action先进行 两千 微秒, 但由于Action 中 sleep(5000),
所以它没执行完,那时拦截器就把请求发到 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); 
                    }); 
                }
}); 

       

 

相关文章