zoukankan      html  css  js  c++  java
  • ognl表达式

    ognl表达式

    action对象是存储在值栈中的,页面提交的数据会通过ognl给action中的属性及对象赋值,页面取值的时候,也是通过ognl从值栈中获取。

    所以数据的传输是通过struts内置的ognl表达式及类型转换来完成,struts内置了类型转换器,来转换八种基本的数据类型。其他的数据类型需要自己手动写类型转换器来实现。

    内置的转换器可以转换日期,但是只支持yyyy-MM-dd这种类型,如果需要其他的日期类型,需要自己开发类型转换器。

    地址类型转换器:将字符串类型的地址转成地址对象

    应用场景:假设在action中有个属性,地址类,private Address comAddress;

    jsp页面为了简化,并没有给address类的每个字段一个输入框,而是只给一个输入框<s:textfield name="comAddress" label="comAddress"/>

    让用户输入公司地址的时候,输入如下信息:福建-厦门-思明-xx街道,

    如果是这样用户提交jsp页面的时候,ognl会把该输入地址(字符串)赋值给comAddress对象,这样就会出现类型不匹配的报错,为了解决这个问题

    必须把用户输入的字符串地址,转换为Address的类型。

    当然如果jsp页面是给四个输入框,则可以不用转换器。

    复制代码
    /**
     * 地址类型转换器
     */
    public class AddressConverter extends StrutsTypeConverter {
    
        /**
         * 将字符串转换成地址对象
         */
        public Object convertFromString(Map context, String[] values, Class toClass) {
            if(values != null && values.length > 0){
                String str = values[0];
                String[] ss = str.split("-");
                if(ss != null && ss.length > 2){
                    Address a = new Address();
                    a.setProvince(ss[0]);
                    a.setCity(ss[1]);
                    a.setStreet(ss[2]);
                    return a ;
                }
            }
            return null;
        }
    
        /**
         * 将地址对象转换成字符串信息
         */
        public String convertToString(Map context, Object o) {
            if(o instanceof Address){
                return o.toString();
            }
            return null;
        }
    
    }
    复制代码

    xwork-conversion.properties配置文件。要放在src根目录下

    struts2.model.Address=struts2.ognl.AddressConverter

    地址类:

    复制代码
    /**
     * 地址类 
     */
    public class Address {
        private String province;
        private String city;
        private String street;
    
        public String getProvince() {
            return province;
        }
    
        public void setProvince(String province) {
            this.province = province;
        }
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        public String getStreet() {
            return street;
        }
    
        public void setStreet(String street) {
            this.street = street;
        }
        
        public String toString() {
            return province + "-" + city + "-" + street;
        }
    }
    复制代码

    ActionContext与ognl

    ognl表达式可以解析任何对象,值栈是其中之一,而且是默认值。

    ActionContext包含了所有范围的数据,共六个(valuestack,request,session,application,attr,parameters)。

    parameters:是request中的请求参数封装到一个map集合中的数据。

    request:是request范围内attribute属性数据,即通过request.setAttribute()设置的数据。

    session:是session范围内attribute属性数据,即通过session.setAttribute()设置的数据。

    application:是application范围内的attribute属性数据,即通过application.setAttribute()设置的数据。

    attr:是从page,request,session,application四个域中查找数据,按照这个查找顺序找到的第一个数据。

    ValueStack:即action中的数据,action中的数据都会放到值栈中。

    ognl表达式可以从这六个范围内取数据,每个ognl表达式解析的时候都需要一个根对象(即需要指定一个域,默认的根对象是值栈)。即默认是从值栈中取数据。

    选取session作为根对象,#session['user'] 表示:从session中取key值为user的对象。相对于session.getAttribute("user");  默认情况下ValueStack是根对象。

    #表示命名对象, 除了可以用ognl取值,还可以用EL表达式。

    ActionContext:数据中心,Threadlocal

    {

      Map context

    }

    OgnlContext实现了Map接口。

    当struts接收到请求后,马上创建一个ActionContext,一个ValueStack和一个Action对象,Action对象会立刻放到值栈上用于ognl访问。并且会放到栈顶。

    顶层对象会覆盖底层对象,有多种方法可以把对象放到栈顶上,比如push标签。

     例如:假设在值栈ValueStack中有对象map,user,xxAction等等对象,map对象在栈顶

    那么当jsp页面有<s:property value="name" />,就会在值栈中从上至下的去搜索name属性的值,如果map中有key为name的值,则返回,

    如果没有继续往下搜索user对象,如果user对象有name属性,则返回,如果没有,继续往下搜索,如果xxAction中有name属性,则返回。

    值栈中可以存放各种类型的数据。

    ognl从值栈中取值的图示:

    数据存储:

    ServletActionContext.getRequest().setAttribute("username", "requestTom");
    ServletActionContext.getRequest().getSession().setAttribute("username", "sessionTom");
    ServletActionContext.getServletContext().setAttribute("username", "applicationTom");
    ServletActionContext.getContext().getValueStack().set("username", "vsTom");
    复制代码
    request.username = <s:property value="#request.username" /><br>从request对象中取值,request不是默认的跟对象,需要加#
    session['username'] = <s:property value="#session.username" /><br>
    application.username = <s:property value="#application.username" /><br>
    attr.username = <s:property value="#attr.username" /><br> parameters.username = <s:property value="#parameters.username" /><br> vs.username = <s:property value="username" /><br>值栈对象默认是根对象,不需要用#
    复制代码

     强制ognl表达式解析 
     例如,label中的值,正常情况下不需要解析,内容会作为一个字符串显示出来,但是如果要想用ognl表达式解析的话,用解析出来的值显示,必须用%{}

    复制代码
            <!-- 强制ognl表达式解析 -->
            <s:textfield name="#session.username" label="%{#request.username}"/><br>
    name="#session.username"是从session中取username的值,
    label="%{#request.username}"从request中取username的值
     
    <s:textfield name="username" label="%{#request.username}"/><br>
    name="username"  是从值栈中取值
     
    复制代码

    Data标签:该类标签用于从值栈中读写数据

    有:property,set,push,bean,action

    property标签:

    如果value找不到值,就会用default的值代替,

    escape:设置是否需要html转义。默认是转义的,即默认会把< 转成&lt;

    <s:property value="'<hr>tom'" escape="false"/> 

    set标签:

    <s:set var="applicationmyname" scope="application" value="#session['username']" />这句话的意思是在application域中存入一个值,key为applicationmyname,值为session域中的username属性值
    <s:property value="#application.applicationmyname" /> 从application域中获取上面存入的值。
    复制代码
    s:set:如果没有指定范围scope的值,则存放ActioinContext自身的map中,<br>
    <s:set var="applicationmyname" value="#session['username']" />
    <s:property value="applicationmyname" />
    这里取值的时候可以加#,也可以不加#,为什么???
    因为ActionContext内存储了其他六个的map集合,而此时没有指定scope也是存储在ActionContext自身的map中,因此是与这六个map同级的。
    ognl搜索的顺序是从六个域的map中找,都找不到,就在自身的map中找。

    复制代码

    set标签是创建值的标签的新的引用,push标签是放置新的属性值到值栈上,当你需要对一个对象进行大量操作时会有用,标签结束后会从栈顶删除该属性,而且该对象只放到值栈上,而set标签可以放到任意的范围中。

    复制代码
    s:push,将对象放到栈顶,标签结束后从栈顶删除<br>
    <s:push value="#application.username">把application中的username放到栈顶
    <s:debug />通过改变这句的位置可以看出是否在栈顶
    <s:property/>如果这么写,表示把栈顶的对象输出,而且会调用对象的tostring()方法 </s:push>

    <s:debug />放到这里,已经从栈顶删除了,username就不在栈顶了
     
    复制代码

    在struts2中很少像java web那样生成的数据通过request.或者session等对象的setAttribuate()方法存到域中,然后再jsp中获取。

    struts2获取数据是通过ognl来访问值栈获取数据,而action运行的时候会加载到值栈中,是根元素,所有在struts2中一般是声明集合list,或者map等属性,

    在action中对该属性赋值,在jsp中通过ognl即可获取。

    action中数据初始化:

    复制代码
    public class OgnlAction extends ActionSupport {
        private List userList ;public List getUserList() {
            return userList;
        }
        public void setUserList(List userList) {
            this.userList = userList;
        }
    
        private void popUserList(){
            userList = new ArrayList<User>();
            User u = null ;
            for(int i = 0 ; i < 10 ; i ++){
                u = new User();
                u.setId(1 + i);
                u.setName("tom" + i);
                u.setAge(20 + i);
                userList.add(u);
            }
        }
    }
    复制代码

    jsp中通过iterator迭代标签取值:

    iteratator标签会把当前要迭代的对象放到栈顶。使用iterator迭代标签迭代的时候,可以不加#,因为此时对象已在栈顶。

    复制代码
    s:iterator,迭代集合属性的<br>
            <table border="1">
                <tr>
                    <td>count</td><td>index</td><td>name</td><td>age</td><td>状态</td>
                    <td>编辑</td><td>查看</td>
                </tr>
                <s:iterator value="userList" var="u" status="st">
                    <tr class='<s:property value="#st.even?'even':'odd'" />'>
                        <td><s:property value="#st.count" /></td>
                        <td><s:property value="#st.index" /></td>
                        <td><s:property value="#u.name" /></td>
                        <td><s:property value="#u.age" /></td>
                        <td>
                            <s:if test="#u.age < 23">少年</s:if>
                            <s:elseif test="#u.age > 27">老年</s:elseif>
                            <s:else>中年</s:else>
                        </td>
                        <td>
                            <s:url action="UserAction_edit" namespace="/user" var="editUrl">
                                <s:param name="id" value="#u.id" />
                                <s:param name="name" value="#u.name" />
                            </s:url>  

    该url标签的值为:/user/UserAction_edit?id=11&name=tom 该值存在editUrl中,在ActionContext大map中
    注意:不带var会直接输出,带var会存在var对应的变量里,该变量在ActionContext维护的大map中
    <a href='<s:property value="#editUrl"/>'>编辑</a>获取该url值 </td> <td><a href='<s:url action="UserAction_view" namespace="/user"><s:param name="id" value="#u.id" /></s:url>'>查看</a></td> </tr> </s:iterator> </table>
    复制代码


    <s:url/>

    假设当前访问的页面为:http://localhost:8080/HelloWorldTest/testaction?name=1&age=12

    <s:url/>输出的值为/HelloWorldTest/testaction
    <s:url includeParams="all"/>输出的值为/HelloWorldTest/testaction?name=1&age=12
    
    
    <s:url includeParams="all" var="myurl"/> 一旦加上var,该标签就不在输出值了,而是把值存在ActionContext大map中,key为myurl
    <s:property value="myurl"/>输出myurl的值
    s:i18n,s:text通常结合在一起使用,访问指定资源文件中的字符串<br>
    <s:i18n name="struts2.action.RegAction_zh">
        <s:text name="label.age" var="mytext"/>
    </s:i18n>
    <s:property value="#mytext"/>

    ogn表达式l操作List,Array:

    list[0],array[0]获取第一个元素

    list[0].name获取第一个元素的name属性值

    array.length

    array.size

    array.isEmpty

    访问集合的大小以及是否为空
    <s:property value="userList.size"/>
    <s:property value="userList.isEmpty"/> 返回true或false
    复制代码
    ognl表示定义集合<br>
    <s:iterator value="{'tom1','hjerry3','tomca5','kking7','jerrli9'}">    构建集合的时候,字符串要用单引号,因为外层有双引号
         <s:property /><br> 遍历value中的各值
    </s:iterator>
    <br>------------------------------------------------------------------------<br>
    ognl定义map集合<br>  创建map的时候前面要加#,创建list不用
    <s:iterator value="#{100:'tom',200:'jerry',300:'kingkong'}">
        key = <s:property value="key" /> : value = <s:property value="value" /><br>
    </s:iterator>
    复制代码

    ogn表达式操作map:

    map['foo'] 或者map.foo 

    map['user'].name 

    map.size

    array.isEmpty

    集合的过滤
    <s:iterator value="userList.{?#this.age > 25}"> 获取userList集合中年龄大于25的对象
        <s:property/><br>  直接这么写,会调用对象的tostring方法,所以如果是对象,一定要重写tostring方法
    </s:iterator>
    集合的投影,即子集
    <s:iterator value="userList.{name}">把userlist集合中的所有name提取出来,构成新的集合
        <s:property/><br>会输出userlist中的各对象的name值
    </s:iterator>

    s:checkbox标签

    s:checkbox<br>
    <s:checkbox name="married" label="婚否" />  在action获取到该值为true或false,因此action中对应该字段要为boolean类型。
    复制代码
    public class UiAction extends ActionSupport {
        private static final long serialVersionUID = -6933309304624396640L;
        /* 婚否 */
        private boolean married = true;//如果没有checkbox拦截器,该值默认为true会出问题,有了checkbox拦截器就解决了这个问题public boolean isMarried() {
            return married;
        }
    
        public void setMarried(boolean married) {
            this.married = married;
        }
    }
    复制代码

    struts提供了checkbox拦截器,其作用是什么?

    防止checkbox对应的属性设置默认的值为true,会带来问题,因为当checkbox没有选中的时候,checkbox标签产生的input表单中就没有value=false的属性,提交到action也就没有该值,这样由于action中设置了默认的值为true,因此就出现了错误。

    checkbox拦截器就解决了这个问题,它在表单中加入了一个隐藏域,无论选中与否都会在隐藏域中保存value值,解决了这个问题。

    所以使用checkbox标签的时候,一定要引入checkbox拦截器。

    s:select标签

    1. 用集合绑定:

    复制代码
    <s:select list="{'tom','jerry','kingkong'}" label="username" />  list是绑定的值,可以从后台获取,也可以在此写死

    生成的html标签的option下拉框的text与value值均为list中的内容
    如:
    <select name="" id="">
      <option value="tom">tom</option>
      <option value="jerry">jerry</option>
      <option value="kingkong">kingkong</option>
    </select>
    复制代码

    2. 用map绑定:

    <s:select list="#{101:'tom',202:'jerry',303:'kingkong'}" label="username"
                    listKey="key" listValue="value"/> 绑定map集合,listkey指定显示的值,listvalue指定绑定的值

     3. 通过后台 Action的userlist集合绑定:

    <s:select list="userList" listKey="id" listValue="name" label="UserName"/>

    ??????如何设定select绑定的初始值?????:通过在action中增加属性selectId,同时在select标签中增加name="selectId"的属性,也后台绑定。

    <s:select name="selectedId" list="userList" listKey="id" listValue="name" label="UserName"/>
    复制代码
    public class UiAction extends ActionSupport {
        private static final long serialVersionUID = -6933309304624396640L;
        
        /* 婚否 */
        private boolean married = true;
        /* javabean集合 */
        private List userList;
        /* 选中的id */
        private Integer selectedId = 10;  绑定select的默认选中值。
    
        public List getUserList() {
            return userList;
        }
    
        public void setUserList(List userList) {
            this.userList = userList;
        }
    
        public String reg() {
            popUserList();
            return "success";
        }
    
        public String toRegView() {
            System.out.println("toRegView");
            return "loginView";
        }
        
        /**
         * 保存数据,
         */
        public String saveData(){
            popUserList();
            popProvinces();
            return "showView" ;
        }
        
        /**
         * 组装用户集合
         */
        private void popUserList(){
            userList = new ArrayList<User>();
            User u = null ;
            for(int i = 0 ; i < 10 ; i ++){
                u = new User();
                u.setId(1 + i);
                u.setName("tom" + i);
                u.setAge(20 + i);
                userList.add(u);
            }
        }
        public Integer getSelectedId() {
            return selectedId;
        }
    
        public void setSelectedId(Integer selectedId) {
            this.selectedId = selectedId;
        }
    }
    复制代码

    s:radio标签:

    <s:radio name="sex" list="#{0:'男',1:'女'}" label="性别" />

    s:checkboxlist标签:

    <s:checkboxlist name="hobby" list="#{0:'足球',1:'篮球',2:'乒乓球'}" label="爱好"/>
    s:doubleselect标签:双选框联动标签
    <s:doubleselect name="selectProvinceId" list="provinces" listKey="id" listValue="areaName"
         doubleName="selectedCityId" doubleList="cities" doubleListKey="id" doubleListValue="areaName"
         label="区域"/>
    复制代码
    public class UiAction extends ActionSupport {
        private static final long serialVersionUID = -6933309304624396640L;/*省集合*/
        private List<Area> provinces ;
         /**
         * 保存数据,
         */
        public String saveData(){
            popUserList();
            popProvinces();
            return "showView" ;
        }
        /**
         * 组装province集合数组
         */
        private void popProvinces(){
            provinces = new ArrayList<Area>();
            Area p1 = new Area(1,"1号省");
            p1.getCities().add(new Area(11,"1.1城市"));
            p1.getCities().add(new Area(12,"1.2城市"));
            p1.getCities().add(new Area(13,"1.3城市"));
            
            Area p2 = new Area(2,"2号省");
            p2.getCities().add(new Area(21,"2.1城市"));
            p2.getCities().add(new Area(22,"2.2城市"));
            p2.getCities().add(new Area(23,"2.3城市"));
            provinces.add(p1);
            provinces.add(p2);
        }public List<Area> getProvinces() {
            return provinces;
        }
    
        public void setProvinces(List<Area> provinces) {
            this.provinces = provinces;
        }
    }
    复制代码
    复制代码
    /**
     * 区域类
     */
    public class Area {
        private Integer id ;
        private String areaName ;
        private String areaNo ;
        private int type ;
        
        /* 省所属城市集合 */
        private List<Area> cities = new ArrayList<Area>();
        
        public Area(Integer id, String areaName) {
            this.id = id;
            this.areaName = areaName;
        }
        
        public Area(Integer id, String areaName, String areaNo) {
            this.id = id;
            this.areaName = areaName;
            this.areaNo = areaNo;
        }
        
        public Area(Integer id, String areaName, String areaNo, int type) {
            this.id = id;
            this.areaName = areaName;
            this.areaNo = areaNo;
            this.type = type;
        }
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getAreaName() {
            return areaName;
        }
        public void setAreaName(String areaName) {
            this.areaName = areaName;
        }
        public String getAreaNo() {
            return areaNo;
        }
        public void setAreaNo(String areaNo) {
            this.areaNo = areaNo;
        }
        public int getType() {
            return type;
        }
        public void setType(int type) {
            this.type = type;
        }
    
        public List<Area> getCities() {
            return cities;
        }
    
        public void setCities(List<Area> cities) {
            this.cities = cities;
        }
    }
    复制代码
  • 相关阅读:
    Struts2框架
    读者写者问题
    哲学家就餐问题
    理解中断
    理解处理机调度
    理解死锁
    理解进程
    Linux CentOS 6.7 挂载U盘
    家庭-养老院模型理解IOC和DI
    Bash基础
  • 原文地址:https://www.cnblogs.com/anzmri/p/8472572.html
Copyright © 2011-2022 走看看