• struts2值栈,OGNL表达式,interceptor


    struts2获取servlet api

    第一种获取方式
      获得原生request
      HttpServletRequest request = ServletActionContext.getRequest();
      获得原生response
      HttpServletResponse response = ServletActionContext.getResponse();
    第二种获取方式
      实现ServletRequestAware,获取原生request
      实现ServletResponseAware,获取原生response

    OGNL表达式

      OGNL是对象图导航语言的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,实现字段类型转化等功能......

      OGNL的作用:支持对象的操作,调用对象的方法,支持静态成员访问,支持静态成员访问,支持赋值操作与表达式串联

    OGNL三要素:表达式 OgnlContext(上下文) Root (根)

    OGNL对象操作:

    @Test
        public void test1() throws Exception {
            //获取ognl对象
            OgnlContext context = new OgnlContext();
            //获取根
            Object root = context.getRoot();
            Object value = Ognl.getValue("'hello'.length()", context, root);
            System.out.println(value);
        }

    OGNL静态成员访问

    @Test
        public void test2() throws Exception {
            //获取ognl对象
            OgnlContext context = new OgnlContext();
            //获取根
            Object root = context.getRoot();
            
            Object value = Ognl.getValue("@java.lang.Math@random()", context, root);
            System.out.println(value);
        }

    如果不能成功执行,是因为struts默认静态成员掉用是关闭的,需要在配置中打开;

    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

    访问OGNL上下文

    @Test
        public void test3() throws Exception {
            //获取ognl对象
            OgnlContext context = new OgnlContext();
            //向上下文中存储数据
            context.put("username", "jack");
            //获取根
            Object root = context.getRoot();
            
            Object value = Ognl.getValue("#username", context, root);
            System.out.println(value);
        }

    ognl操作集合

    @Test
        public void test4() throws Exception {
            //获取ognl对象
            OgnlContext context = new OgnlContext();
            //获取根
            Object root = context.getRoot();
            
            Object value = Ognl.getValue("{'111','222','333'}", context, root);
            //这里就相当于建立了一个list集合
            System.out.println(value);
            //把list集合放入root根中
            context.setRoot(value);
            //获取list中的数据
            Object value2 = Ognl.getValue("[1]", context, context.getRoot());
            System.out.println(value2);
        }

    这里需要特别注意的是:这里的root不能用上面的root,用上面的root会取不到list中的值

      在struts2框架中我们使用ognl表达式的作用是从valueStack中获取数据,我们在struts2框架中可以使用
    ognl+valueStack达到在页面上来获取数据,这就需要使用<s:property value="表达式">来使用

    要使用<s:property value="表达式">就要导入核心标签库

    <%@taglib prefix="s" uri="/struts-tags" %>

    下面就可以使用:

    <s:property value="'hello'.length()"/>
    <s:property value="@java.lang.Math@random"/>

    下面介绍非常重要的值栈

      我们使用valueStack的主要目的是将action中的数据带到jsp页面,它就是一个容器;
      在struts2中它就是一个接口:com.opensymphony.xwork2.util.ValueStack
      它的实现类是:com.opensymphony.xwork2.ognl.OgnlValueStack

    struts2中的action是一个多例的,每一次请求都会有一个新的action对应,所以它不存在线程安全问题;
    一个valueStack对应一个action,valueStack贯穿整个action;
    request--action--actionContext--valueStack
    所以valueStack保存在request中

    valueStack由两部分组成:

      CompoundRoot:它就是一个arraylist,主要用于存储action的相关数据
      Map<String,Object> context:就是一个map,主要用于存储一些引用,关于web开发中的相关信息
      pameters :请求参数
      request:请求对象中所有属性
      session:会话对象中所有属性
      application:application对象中的所有发展

    struts2框架中使用ognl表达式来获取valueStack中的数据,使用#就是从非root根中获取数据

      获取valueStack的两种方式

      1.直接通过request获取

    @Test
        public void test1() {
            //通过request获取
            ValueStack vs = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
        }

      2.使用actionContext来获取

    @Test
        public void test2() {
            //通过actioncontext来获取
            ActionContext context = ActionContext.getContext();
            ValueStack valueStack = context.getValueStack();
        }

    那么actionContext到底是什么呢:

      

      它是action的上下文对象,struts2使用它来保存action在执行过程中所需要的一些对象,例如:session,application
      它通过getContext()静态方法得到
      struts2会根据每一次的request请求创建actionContext,它是与线程绑定的,每一次请求就是每一个线程,每一个request
      都会创建一个action,每个action对应一个actionContext,所以每一次请求也对应着一个valueStack

      特别注意的是:valueStack存储数据的时候,主要是向root中存储;

      对于继承了ActionSupport类的action类,浏览器传入的数据是存储在model对象中;

      使用了表达式也可以从value中获取数据是因为struts2对request中的getAttribute进行了增强,,如果request域中找不到数据,就会
    在valueStack中获取

    ognl中的特殊字符

      #号:代表的是从飞root中获取数据
      %:用户强制是否要解析ognl表达式
      $:主要是从配置文件中来获取valueStack中数据

    一个展示商品信息的例子

      在jsp页面中点击显示商品的连接,然后封装商品,保存然后跳转到showProduct页面

    <a href="${pageContext.request.contextPath }/Demo3Action">显示商品</a>

    跳转到action中处理数据:

    public class Demo3Action extends ActionSupport{
        //封装product的数据
        public String show() throws Exception {
            List<Product> list = new ArrayList<>();
            //模拟数据
            Product p1 = new Product();
            p1.setName("电视");
            p1.setCount(100);
            p1.setPrice(2000);
            Product p2 = new Product();
            p2.setName("冰箱");
            p2.setCount(200);
            p2.setPrice(1000);
            //存储到集合
            list.add(p1);
            list.add(p2);
            //保存到值栈中
            ValueStack vs = ActionContext.getContext().getValueStack();
            System.out.println(list);
            vs.set("list", list);
            return "show";
        }
        
    }

    跳转到显示页面

         <s:iterator value="list">
                <tr>
                    <td><s:property value="name"/></td>
                    <td><s:property value="count"/></td>
                    <td><s:property value="price"/></td>
                </tr>
            </s:iterator>

    拦截器

      struts2的拦截器主要是拦截action的操作,在action的执行前或后进行一些其它功能的操作

    执行过程

      当我们发送请求访问Action时,会被StrutsPrepareAndExecuteFilter拦截

    在其doFilter方法内执行了

      

    execute.executeAction(request, response, mapping);

    这个代码执行后

      

    dispatcher.serviceAction(request, response, mapping);

    serviceAction方法执行

      在这个方法执行过程中会创建Action代理对象

    ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                        namespace, name, method, extraContext, true, false);

      通过proxy去执行了proxy.execute();
      在execute方法内return invocation.invoke();
      invocation它是ActionInvocation一个对象
      在invoke方法内,会去加载我们的配置文件,将配置文件中所有的interceptor得到进行遍历。
      在struts-default.xml文件中定义了默认加载的拦截器栈 defaultStack
      在每一个拦截器的interceptor方法内,又调用了DefaultActionInvocation的invoke方法,其实就是递归调用。

    自定义interceptor

      所有的Interceptor都要实现一个接口
      在配置文件中声明Interceptor

    <interceptors>
            <interceptor name="" class=""></interceptor>
    </interceptors>

      我们也可以将多个interceptor封装成一个stack

    <interceptors>
            <interceptor name="interceptor1" class=""></interceptor>
            <interceptor name="interceptor2" class=""></interceptor>
            <interceptor-stack name="myStack">
                <interceptor-ref name="interceptor1"></interceptor-ref>
                <interceptor-ref name="interceptor2"></interceptor-ref>
            </interceptor-stack>
    </interceptors>

    注意:当我们显示的引入了一个自定义的Interceptor,那么默认的defaultStack就不会在导入,需要手动导入。

  • 相关阅读:
    作业,注册页面
    HTML表单
    用HTML制作简历
    多线程同步标记
    集合类
    多态 接口
    java 泛型讲解
    转型
    使用super关键字
    作业题
  • 原文地址:https://www.cnblogs.com/learnjfm/p/7090759.html
Copyright © 2020-2023  润新知