Struts2框架-2

struts2修改浏览器请求后缀的配置
struts2默认是action的后缀或者为空;访问时后缀不是默认值则报错
在struts.xml文件中配置以下元素
<constant name="struts.action.extension" value="do" ></constant >
该配置的作用:把浏览器请求的后缀该为.do;访问时不是.do则报错



result节点
    result是action节点的子节点
    result代表action方法执行后可能去的一个网页
    result的name是action执行的返回结果
    一个action可以有多个result
    result的type属性,定义了返回结果的类型——dispatcher(转发,是默认值)、redirect(重定向到页面)redirectAction(重定向到一个action中继续执行,不展示数据)、chain(转发到一个action中继续执行代码,不展示数据)
        重定向/转发到action时,需要配置重定向的action的配置
        <param name="actionName"></param>
        <param name="namespace"></param>(可以通过redirect间接实现重定向到action中,转发到action中不能使用dispatcher间接实现)



通配符映射

一个web应用可能有成百上千个action,可以利用struts2提供的通配符映射机制把多个彼此相似的映射关系简化为一个映射关系,便以维护
通配符映射规则:
若找到多个匹配,没有通配符的那个(精确匹配)将胜出;
若指定的动作不存在,struts2将会尝试把这个URI与任何一个包含着通配符*的动作名进行匹配;
被通配符匹配到的URI字符串的子串可以用{1}、{2}来引用,{1}匹配第一个子串,{2}匹配第二个子串;
{0}匹配整个URI;
若struts2找到的带有通配符的匹配不止一个,则按先后顺序进行匹配;
*可以匹配零个或多个字符,但不包括'/'字符,若想把‘/’包含在内,需要使用‘**’,如果需要对某个字符进行转义,需要使用'\'。
例:<action name="user-add" class="...." method="add">
         <result name="add-user">.....</reslut>
    </action>
    <action name="user-delete" class="...." method="delete">
         <result name="delete-user">.....</reslut>
    </action>
    <action name="user-update" class="...." method="update">
         <result name="update-user">.....</reslut>
    </action>
    <action name="user-look" class="...." method="look">
         <result name="look-user">.....</reslut>
    </action>
可改为以下通配:
    <action name="user-*" calss="....." method="{1}">
        <result name="{1}-user">.....</result>
    </action>



动态方法调用(不推荐使用)
动态方法调用: 通过 url 动态调用 Action 中的方法,忽略配置文件中的action声明

    URI1:/struts-app2/Product.action: Struts 调用 Product 类的 execute

    URI2:/struts-app2/Product!save.action:Struts调用Product类的save() 方法 

struts2中默认禁用动态方法调用
添加配置激活才能使用
      <constant   name="struts.enable.DynamicMethodInvocation"  value="true">
      </constant>




OGNL表达式


关于值栈
1:${xx.xx}读取xx.xx值,实际上该属性并不在request等域对象中,而是从值栈中获取的。
2:值栈的获得:可以从ActionContext中获取值栈对象
3:值栈可以分为两个逻辑部分
    Map栈:实际上是OgnlContext类型,是Map类型,也是对ActionContext的一个引用,里面保存着各种Map对象(requestMap、sessionMap、applicationMap等),该栈中,Map按照request、Parameter、session、application的顺序检索某个属性。
    对象栈:实际上是CompoundRoot类型,是一个使用ArrayList定义的栈,里面保存各种和当前Action实例相关的对象(数据结构意义的栈)
4:每一个action都有自己的值栈,贯穿整个action生命周期,相当于数据中转站。

OGNL:在JSP页面上可以利用OGNL(Object-Graph Navigation Language对象-图导航语言)访问到值栈里的对象属性,如果想要访问值栈中ContextMap中的数据,需要给OGNL表达式加上一个前缀字符‘#’,如果没有前缀字符‘#’,搜索将在ObjectStack里进行。

Struts2中利用 property 标签和OGNL表达式用来输出值栈中的某一个对象的属性值。
读取对象栈中的属性(以下几种方式):
    object.propertyName;(推荐使用)
    object['properName'];
    object["properName"];
    [0].message;//表示栈定的对象的message属性   [n].message;//表示从第n个对象开始检索message属性,若从栈顶检索,可省略下标
例:<s:property value="message"/>或者<s:property value="[0].message"/>



读取ContextMap里的属性(以下几种方式):
      #Object.propertyName;
      #object['propertyNmae'];
      #object["propertyNmae"];
      #session.code;;
      #request.customer.name;
例:<s:property value="#session.property.name">
    可以改为EL表达式:Name:${session.property,name}


OGNL还可以调用public类的public类型的静态方法和静态属性
默认情况下,struts2不允许调用任意JAVA类的静态方法,需要重新设置
   <constant name="struts.ognl.allowStaticMerhodAccess"    value="true"></constant>
    @java.util.Calendar@DECEMBER//调用静态属性
    @app4.Util@now()//调用静态方法


OGNL还可以访问数组类型:用下表访问指定元素(colors[0])
OGNL还可以访问List类型:用下标访问指定元素(colors[0]),调用方法(colors.size();colors.isEmpty())
OGNL还能访问Map类型:读取一个Map类型的属性将返回所有的键值对({key-1=Value-1,key-2=value-2.......});map[key]来查找某一个键值对



EL表达式:来取代JSP中的表达式,是JSP页面看起来更加清晰!<br>
EL表达式的语法:以"${"开始,以"}"结束<br>
EL表达式的用法:1:EL表达式内部可以直接进行算术运算,比较运算,逻辑运算,三目运算并将结果显示在页面<br>
${1+1}<br>
${2>5 }<br>
${!true }<br>
用法2:EL表达式可以用来访问JSP内置对象中保存的对象<br>
${requestScope.name }<br>
${name }<br>
获取数组中的内容<br>
${mys[0] }<br>
${mys[1] }<br>
${mystu.sid }<br>
${mystu.sname }<br>
${mymap.school } 或者${mymap["school"] }<br>
获取List集合的数据:${mylist[0] }${mylist[1] }<br>
获取list1集合的学生对象:${students[0].sname }${students[0].sid }或者${students[2].sname} ${students[2].sid }


能用EL表达式的地方一般都能使用OGNL表达式,但是能用OGNL表达式的地方,不一定能使用EL表达式(struts2中重写了Servlet的一些方法,使用EL表达式不一定能获取到值)







struts2声明式异常处理
exception-mapping 元素: 配置当前 action 的声明式异常处理
例如:<action name=".....">
         <exception-mapping result="xxx" exception="java.lang.exception">
         ......</exception-mapping>
         <result name="xxx"></result>
      </action>
    
exception-mapping 元素中有 2 个属性
  exception: 指定需要捕获的的异常类型。异常的全类名
  result: 指定一个响应结果, 该结果将在捕获到指定异常时被执行, 既可以来自当前 action 的声明, 也可以来自 global-results 声明。
    
可以通过 global-exception-mappings 元素为应用程序提供一个全局性的异常捕获映射. 但在 global-exception-mappings 元素下声明的任何 exception-mapping 元素只能引用在 global-results 元素下声明的某个 result 
例如:<global-results>
          <result name="xxx">......</result>
      </global-results>
      <global-exception-mappings>
          <exception-mapping result="xxx" exception="java.lang.Exception">
          </exception-mapping>
      </global-exception-mappings>

元素声明式异常处理机制由  ExceptionMappingInterceptor 拦截器负责处理, 当某个 exception-mapping 元素声明的异常被捕获到时,ExceptionMappingInterceptor 拦截器就会向ValueStack 中添加两个对象: 
exception: 表示被捕获异常的 Exception 对象
exceptionStack: 包含着被捕获异常的栈
可以在视图上通过 <s:property> 标签显示异常消息(用OGNL或者EL表达式)




通用标签

在JSP页面中需要添加
<%@ taglib uri="/struts-tags" prefix="s" %>
1:property 标签用来输出一个值栈属性的值
       例:<s:property value=“customerId”/>如果 value 属性没有给出, ValueStack 值栈栈顶对象的值被输出
在许多情况下, JSP EL 可以提供更简洁的语法


2:url 标签用来动态地创建一个 URL
      例如:<s:url value="/xxx" var"url" namespace="..." action="...">
               ${url }
            </s:url>
     <s:url value="/xxx" var"url" namespace="..." action="...">
       <s:param  name="xx" value="xx"></s:param>//会自动进行OGNL解析Value值
     </s:url>
        <s:url action="xxx" namespace="xxxx" method="xx" var="url"></s:url>


3:param 标签用来把一个参数传递给包含着它的那个标签
    无论在给出 value 值时有没有使用 %{}, Struts 都会对它进行 ognl编译,如果想传递一个 String 类型的字符串作为参数值, 必须把它用单引号括起来。可以把 value 属性的值写在开始标签和结束标签之间. 利用这种方式来传递一个 EL 表达式的值。


4:set 标签用来在以下 Map 对象里创建一个键值对:
ValueStack 值栈的 ContextMap 值栈Map 类型的 session 对象
Map 类型的 application 对象
Map 类型的 request 对象
Map 类型的 page 对象
例如:<s:set name="xxx" value="值栈中的值" scopr="xx"></s:set>//会自动进行OGNL解析Value值


5:push 标签的功能和 set 标签类似.
push 标签将把一个对象压入 ValueStack 而不是压入 ContextMap。
push 标签在标签起始时把一个对象压入栈, 标签结束时将对象弹出栈。
例如:<s:push value="#AA">
      ${AA}
   </s:push>


6:这三个标签用来进行条件测试, 它们的用途和用法类似于 if, else 和 elseif 关键字. 其中 if 和 elseif 必须有 test 属性
例如:<s:if  test="判断">执行代码</s:if>
      <s:elseif test="判断">执行代码</s:>
      <s:else>执行代码</s:>


7:iterator 标签用来遍历一个数组, Collection 或一个 Map, 并把这个可遍历对象里的每一个元素依次压入和弹出 ValueStack 栈。
例如:<s:iterator value="值栈中的集合或数组">
         执行代码(不用考虑循环,只需要对数据进行操作)

      </s:iterator>


8:sort 标签用来对一个可遍历对象里的元素进行排序(排序的元素需要实现comparator接口的compare方法())
例如:<s:sort comparator="元素的集合对象" source="元素" 
         var="新的存储的集合引用">
    </s:sort>

9:date 标签用来对 Date 对象进行排版      

format 属性的值必须是 java.text.SimpleDateFormat 类里定义的日期/时间格式之一

例如:<s:date name="时间对象" format="排版方式:yyyy-MM-dd hh:mm:ss" var="排版后的时间对象引用"></s:date>



10:a 标签将呈现为一个 HTML 连接. 这个标签可以接受 HTML 语言中的 a 元素所能接受的所有属性。 
例如:<s:a href="URL"></s:a>//使用%{}把属性括起来写在URL中可以进行OGNL解析



表单标签
优点:表单回显;对页面进行布局和排版

1:form标签——表单具有自动回显(值栈栈顶开始检索),排版功能
   <s:form action="xxxxx">
     <s:textfield name="userName" label="UserName"></s:textfield>
     <s:password name="password" label="password"></s:password>
     <s:textarea name="desc" label="Desc"></s:textarea>
     <s:checkbox name="sex" label="Sex"></s:checkbox>  //将呈现为一个 HTML复选框元素. 该复选框元素通常用于提交个布尔值,当包含着一个复选框的表单被提交时, 如果某个复选框被选中了, 它的值将为 true, 这个复选框在 HTTP 请求里增加一个请求参数.但如果该复选框未被选中, 在请求中就不会增加一个请求参数。
     <s:submit></s:submit>
   </s:form>

   list, listKey, listValue 这 3 个属性对 radio, select, checkboxlist 等标签
非常重要。可以把一个 String, 一个数组, 一个 Enumeration, Iterator, Map 或 Collection 赋给 list 属性。
   把数组或 Collection或者Map或者Iterator或者Enumeration赋值给 list 属性, 把用来提供选项值的对象属性赋给 listKey 属性, 把用来提供选项内容的对象属性赋给 listValue 属性。(使用这些标签是使用集合类保证正常回显)



2:checkboxlist 标签——将呈现一组多选框
例如:
<s:checkboxlist list="#xxx" listKey="List中的对象的属性"  value="List中的对象的属性" label="xxxx" name="xxxxx"></s:checkboxlist>


3:radio 标签——将呈现为一组单选按钮,单选按钮的个数与程序员通过该标签的 list 属性提供的选项的个数相同。
一般地,使用 radio 标签实现 “多选一”, 对于 “真/假” 则该使用 checkbox 标签。
例如:
<s:radio name="xx" label="xxx" list="xxList"></s:radio>


4:select 标签——将呈现一个 select 元素(下拉菜单)。
<s:selec name="xxx" label="xxxx" list="xxMap" listKey="Map.xx" listValue="Map.xxx"/>


5:optiongroup 标签——对select元素所提供的选项进行分组。每个选项有它自己的来源。
例如:
<s:selec name="xxx" label="xxxx" list="xxMap" listKey="Map.xx" listValue="Map.xxx">
<s:optgroup label="xxx" list="#xxx"></s:optgroup>//用于显示更多的下拉菜单
</s:select>




主题(css样式)

<!-- 设置ui标签的主题:作用是让生成的ui标签去掉自带的样式 -->
<constant name="struts.ui.theme" value="simple"></constant>
<constant name="struts.ui.templateDir" value="template"></constant>
<constant name="struts.ui.templateSuffix" value="ftl"></constant>



拦截器
增删改查操作(CRUD操作)配置如下:
<action name="user-*" class="xxx.xx.xx" method="{1}">
    <result name="{1}">/user-{1}.jsp</result>
</action>
class类中是操作user增删改查的具体方法,展示在对应的页面(/user-{1}.jsp)


Actionproxy是Action的一个代理类,也就是说Action的调用是通过ActionProxy实现的,就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法。
ActionInvocation就是action的调用者,它负责struts2的拦截器(interceptor)、action以及Result等一系列元素的调用。
调用一个action时,所有的拦截器都会执行一遍,按照struts2的默认配置顺序。


Params拦截器
Parameters 拦截器将把表单字段映射到 ValueStack 栈的栈顶对象(默认为Action对象)的各个属性中. 如果某个字段在模型里没有匹配的属性, Param 拦截器将尝试 ValueStack 栈中的下一个对象。


ModelDriven拦截器

   在使用 Struts 作为前端的企业级应用程序时把 Action 和 Model 清晰地隔离开是有必要的,有些 Action 类不代表任何Model 对象, 它们的功能仅限于提供显示服务。
   如果 Action 类实现了ModelDriven接口,该拦截器将把 ModelDriven 接口的getModel()方法返回的对象置于栈顶
。用于Params拦截器把表单字段映射到值栈栈定元素。
   注意: getModel 方法不能提供以下实现. 的确会返回一个 Employee 对象到值栈的栈顶。但当前 Action 的 employee 成员变量却是 null。会对修改信息时,表单的回显造成影响。


prepare 拦截器

   它负责准备为 getModel() 方法准备 model,以便modelDriven拦截器使用。Struts2 将尝试执行prepare[ActionMethodName] 方法,若 prepare[ActionMethodName] 不存在, 则将尝试执行 prepareDo[ActionMethodName] 方法,若都不存在, 就都不执行。
    然后将会个根据prepare的属性alwwysInvokePrepare(Boolean类型)的值选择是否执行prepare()方法,可自定义,配置文件见下文。



使用prepare拦截器要实现Preparable接口;使用modelDriven拦截器要实现ModelDriven接口。



struts2默认拦截器栈(defaultStack
<interceptor-stack name="defaultStack">
    <interceptor-ref name="exception"/>
    <interceptor-ref name="alias"/>
    <interceptor-ref name="servletConfig"/>
    <interceptor-ref name="i18n"/>
    <interceptor-ref name="prepare"/>——准备model
    <interceptor-ref name="chain"/>
    <interceptor-ref name="scopedModelDriven"/>
    <interceptor-ref name="modelDriven"/>——实现接口后,把返回对象置于值栈栈顶
    <interceptor-ref name="fileUpload"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="multiselect"/>
    <interceptor-ref name="staticParams"/>
    <interceptor-ref name="actionMappingParams"/>
    <interceptor-ref name="params">——把表单字段映射到值栈栈定对象的属性中
       <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parametes\...*</param>
    </interceptor-ref>
    <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-stack>




Struts2调用类中的方法实现某些功能时,会根据配置信息进行调用,当实现了ModelDriven接口后,调用getModel()方法时,需要判断属性,但是使用默认拦截器栈(defaultStack)无法实现,先调用了modelDriven拦截器,才去调用params拦截器。把拦截器栈修改为paramsPrepareParamsStack就可以调用,paramsPrepareParamsStack拦截器的实现顺序见下文。
修改拦截器栈的配置方式:
<default-interceptor-ref name="paramsPrepareParamsStack"></default-interceptor-ref>



public class EmployeeAction implements RequestAware, ModelDriven<User>, Preparable{
private Dao dao = new Dao();
private User user;
private Integer userId;
private Map<String, Object> request;

public void setUserId(Integer userId) {
this.userId = userId;
}

public String update(){
dao.update(user);
return "success";
}
public void prepareUpdate(){
user = new User();
}//量身定做的Update的model生成方法()

public String edit(){
return "edit";
}
public void prepareEdit(){
user = dao.get(userId);
}//量身定做edit的model生成方法()

public String save(){
dao.save(user);
return "success";
}
public void prepareSave(){
user = new User();
}//量身定做的save的model生成方法()

public String delete(){
dao.delete(userId);
return "success";
}//不需要model,不用实现prepareDelete()方法
public String list(){
request.put("users", dao.getUser());
return "list";
}
@Override
public void setRequest(Map<String, Object> arg0) {
this.request = arg0;
}
@Override
public User getModel() {
return user;
}
@Override
public void prepare() throws Exception {
System.out.println("prepare...");
}
}



paramsPrepareParamsStack拦截器栈

<interceptor-stack name="paramsPrepareParamsStack">
    <interceptor-ref name="exception"/>
    <interceptor-ref name="alias"/>
    <interceptor-ref name="i18n"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="multiselect"/>
    <interceptor-ref name="params">——把表单字段映射到值栈栈定对象的属性中
       <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request           \..*,^application\..*,^servlet(Request|Response)\..*,parameter\...*</param>
    </interceptor-ref>
    <interceptor-ref name="servletConfig"/>
    <interceptor-ref name="prepare"/>——准备model
   <interceptor-ref name="chain"/>
    <interceptor-ref name="modelDriven"/>——实现接口后,把返回对象置于值栈栈顶
    <interceptor-ref name="fileUpload"/>
    <interceptor-ref name="staticParams"/>
    <interceptor-ref name="actionMappingParams"/>
    <interceptor-ref name="params">——把表单字段映射到值栈栈定对象的属性中
       <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request           \..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
    </interceptor-ref>
    <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-stack>

paramsPrepareParamsStack 从字面上理解来说, 这个stack的拦截器调用的顺序为:首先 params,然后 prepare,接下来 modelDriven,最后再 params 。

流程如下:
1. params拦截器首先给action中的相关参数赋值,如id
2. prepare拦截器执行prepare方法,prepare方法中会根据参数,如id,去调用业务逻辑,设置model对象 
3. modelDriven拦截器将model对象压入value stack,这里的model对象就是在prepare中创建的 
4. params拦截器再将参数赋值给model对象
5. action的业务逻辑

   PrepareInterceptor  的 alwaysInvokePrepare 属性为 false(默认为true,会调用该方法), 则 Struts2 将不会调用实现了 Preparable 接口的  Action 的 prepare() 方法。

   配置文件可配置为:
   <interceptors>
     <interceptor-stack name="CRUDStack">
        <interceptor-ref name="paramsPrepareParamsStack">
            <param name="prepare.alwwysInvokePrepare">false</param>
        </interceptor-ref>
     </interceptor-stack>
   </interceptors>
   <default-interceptor-ref name="CRUDStack"/>——自定义的拦截器栈




自定义拦截器——满足某些特殊功能
例子:该拦截器可以计算运行时间、验证登陆等特殊功能
    <!-- 配置拦截器(计算Action运行时间和验证登陆) -->

    <interceptors>

        <!--自定义的拦截器-->

        <interceptor name="actiontime" class="com.userIncepter.ActionRuntime"></interceptor>
        <interceptor name="actioncheckuser" class="com.userIncepter.CheckUser"></interceptor>
<!-- 定义拦截器栈(在包内,全局调用自定义拦截器) -->
    <interceptor-stack name="UserStack">
       <!-- 引用拦截器actiontime -->
       <interceptor-ref name="actiontime"></interceptor-ref>
       <interceptor-ref name="actioncheckuser">
           <!-- 设置白名单 (加入白名单的将会被拦截,属于默认值)-->
    <!--<param name="includeMethods">方法名(多个则加逗号)</param>-->
    <!-- 设置黑名单(加入黑名单的方法将不会被拦截)-->
    <param name="excludeMethods">userLogin</param>
       </interceptor-ref>
       <!-- 重新引用底层拦截器(引用其他拦截器后会失效) -->
       <interceptor-ref name="defaultStack"></interceptor-ref>
    </interceptor-stack>
    </interceptors>
   
    <!-- 启动拦截器 -->

    <default-interceptor-ref name="UserStack"></default-interceptor-ref>



未完待续,且听下回分解!




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值