传智播客 struts2 Action 配置种类与OGNL总结

 

     与struts1流程相比,struts2的流程相对来说比较简单。StrutsPrepareAndExecuteFilter是Struts 2框架的核心控制器,它负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入Struts 2框架处理,否则Struts 2框架将略过该请求的处理。当请求转入Struts 2框架处理时会先经过一系列的拦截器,然后再到Action。Action执行完后,就转入相应的视图并返回响应给客户端。与Struts1不同,Struts2对用户的每一次请求都会创建一个Action,所以Struts2中的Action是线程安全的。
    在大部分应用里,随着应用规模的增加,系统中Action的数量也会大量增加,导致struts.xml配置文件变得非常臃肿。为了避免struts.xml文件过于庞大、臃肿,提高struts.xml文件的可读性,我们可以将一个struts.xml配置文件分解成多个配置文件,然后在struts.xml文件中包含其他配置文件。下面的struts.xml通过<include>元素指定多个配置文件:
      <struts>
          <include file="struts-user.xml"/>
          <include file="struts-order.xml"/>
      </struts>
    在struts1中,一个Action如果继承了DispatchAction,就能派发请求给不同的方法进行处理。在struts2中有两种方式实现类似功能。一是当Action中存在多个方法时,我们可以直接使用!+方法名调用指定方法。假设一个Action中有execute和other两个方法,正常情况下访问execute方式的URL路径为:/struts/test/helloworld.action,如果要访问action的other() 方法,就可以这样调用:/struts/test/helloworld!other.action。动态调用很少被使用,一般都是采取后面介绍的那种方式来派发请求。如果不想使用动态方法调用,我们可以通过常struts.enable.DynamicMethodInvocation关闭动态方法调用。使用通配符定义action也比较简单,首先是在action元素的name属性处采用一个*号通配符,然后在method属性处用一个占位符。如下所示:
      <action name="helloworld_*" class="com.yxb.struts.HelloWorld" method="{1}">
    如果要访问other()方法,可以通过这样的URL访问:/test/helloworld_other.action。
    如果使用的是2.1.8版本之前的struts2,则在程序中需要解决乱码问题。struts2.1.6版本中存在一个Bug,即接收到的中文请求参数为乱码(以post方式提交),原因是struts2.1.6在获取并使用了请求参数后才调用HttpServletRequest的setCharacterEncoding()方法进行编码设置 ,导致应用使用的就是乱码请求参数。这个bug在struts2.1.8中已经被解决,如果你使用的是struts2.1.6,要解决这个问题,你可以这样做:新建一个Filter,把这个Filter放置在Struts2的Filter之前,然后在doFilter()方法里添加以下代码:
      HttpServletRequest req = (HttpServletRequest) request;
      req.setCharacterEncoding("UTF-8");//应根据你使用的编码替换UTF-8
      filterchain.doFilter(request, response);
    在struts2中,默认的表达式语言是OGNL,Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts 2框架使用OGNL作为默认的表达式语言。相对EL表达式,它提供了平时我们需要的一些功能,如:支持对象方法调用,支持类静态方法调用和值访问,操作集合对象。例如():
      访问值栈中的action的普通属性: username = <s:property value="username"/>
      访问值栈中对象的普通属性(get set方法):<s:property value="user.age"/> | <s:property value="user['age']"/>
      访问静态方法:<s:property value="@com.yxb.struts2.ognl.Test@s()"/>
      访问静态属性:<s:property value="@com.yxb.struts2.ognl.Test@S"/>
      访问Math类的静态方法:<s:property value="@@max(2,3)" />
      访问普通类的构造方法:<s:property value="new com.yxb.struts2.ognl.User()"/>
      访问List:<s:property value="users"/>
      访问List中某个元素:<s:property value="users[1]"/>
      访问List中元素某个属性的集合:<s:property value="users.{age}"/>
      访问List中元素某个属性的集合中的特定值:<s:property value="users.{age}[0]"/> | <s:property value="users[0].age"/>
    看看上面的实例代码如此方便的就访问到相应的属性。那它的原理是什么呢?Ognl 有一个上下文Context概念,其实这个上下文就是一个MAP结构,它实现了java.utils.Map接口,在Struts2中上下文Context的实现为ActionContext,当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action对象存放进ValueStack,所以action的实例变量可以被OGNL访问。
    在放入action对象到值栈中的同时,与ValueStack平行的还有代表request,session,application的Map结构,当在程序中往这些Map中放入对象时,也就相当于与放入了相应的Servlet域对象中。在struts2中,OGNL会设定一个根对象,该根对象就是ValueStack(值栈)。如果要访问根对象中对象的属性,可以直接访问该对象的属性,就如同上面看到的那样。在struts2中,根对象ValueStack的实现类为OgnlValueStack,该对象不是我们想像的只存放单个值,而是存放一组对象。在OgnlValueStack类里有一个List类型的root变量,就是使用他存放一组对象。在root变量中处于第一位的对象叫栈顶对象。通常我们在OGNL表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。
    由此看来struts2中存储对象的Map比较多,不肯能跟直接去访问它们。所以当药访问相应范围内的属性时就需要使用#符号标注命名空间,如#application、#session等,这样struts2就会去相应的范围类去寻找。有一点值得注意的是OGNL表达式需要配合Struts标签才可以使用。
    struts2是由黎活明老师讲解的,黎老师的讲课风格比较清晰,简单高效,能抓住问题的重点与本质。还有一点就是黎老师对原理讲解的比较透彻,深入。由于最后课程安排比较紧,通常时间都是不够用的,每天下午讲到6点是家常便饭,有的时候还能超过这个时间。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值