struts2入门学习


       

如何搭建Struts2项目





导入相关架包





编写web.xml,配置strus2过滤器





    <filter> 
  
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9




编写Struts2配置文件struts.xml





    <?xml version="1.0" encoding="UTF-8" ?> 
  
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">

    <struts>
        <package name="default" namespace="/user" extends="struts-default">
            <action name="regist" class="cn.itcast.action.RegistAction">
                <result name="input">/success.jsp</result>
            </action>
        </package>
    </struts>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11


访问路径 /user/regist.action

name 包名称,在struts2的配置文件文件中 包名不能重复 ,name并不是真正包名,只是为了管理Action 

namespace 和 action的name属性,决定 Action的访问路径  (以/开始 )

extends 继承哪个包,通常开发中继承 struts-default 包 (struts-default包在 struts-default.xml定义 )

继承struts-default包后,可以使用 包中定义拦截器和结果类型 

action元素配置默认值 

package 的namespace 默认值‘’‘’ 

action 的class 默认值 ActionSupport 类 

result 的 name 默认值 success





默认Action 和 Action的默认处理类



1) 默认Action , 解决客户端访问Action不存在的问题 ,客户端访问Action, Action找不到,默认Action 就会执行 

   



2) 默认处理类 ,客户端访问Action,已经找到匹配元素,但是元素没有class属性,执行默认处理类 

    

    * 在struts-default.xml 配置默认处理类 ActionSupport





Struts2的常量配置



1) struts2 默认常量 在 default.properties 中配置 

2) 开发者自定义常量





    struts.xml 
  
        格式 : <constant name="struts.devMode" value="true" />
    struts.properties
        格式 : struts.devMode = true
    web.xml
        格式 :
        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
            <init-param>
                <param-name>struts.devMode</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14


3) 常用常量



<constant name="struts.i18n.encoding" value="UTF-8"/>  ----- 相当于request.setCharacterEncoding("UTF-8"); 解决post请求乱码 
  
<constant name="struts.action.extension" value="action"/>  --- 访问struts2框架Action访问路径 扩展名 (要求)
struts.action.extension=action, 默认以.action结尾扩展名 和 不写扩展名 都会分发给 Action
<constant name="struts.serve.static.browserCache" value="false"/> false不缓存,true浏览器会缓存静态内容,产品环境设置true、开发环境设置false
<constant name="struts.devMode" value="true" />  提供详细报错页面,修改struts.xml后不需要重启服务器




Action





Action书写的的三种格式





第一种



Action可以是 POJO  ((PlainOldJavaObjects)简单的Java对象) —- 不需要继承任何父类,实现任何接口

    * struts2框架 读取struts.xml 获得 完整Action类名 

    * obj = Class.forName(“完整类名”).newInstance();

    * Method m = Class.forName(“完整类名”).getMethod(“execute”);  m.invoke(obj); 通过反射 执行 execute方法





第二种



编写Action 实现Action接口 

    Action接口中,定义默认五种 逻辑视图名称 

    public static final String SUCCESS = “success”;  // 数据处理成功 (成功页面)

    public static final String NONE = “none”;  // 页面不跳转  return null; 效果一样

    public static final String ERROR = “error”;  // 数据处理发送错误 (错误页面)

    public static final String INPUT = “input”; // 用户输入数据有误,通常用于表单数据校验 (输入页面)

    public static final String LOGIN = “login”; // 主要权限认证 (登陆页面)

     五种逻辑视图,解决Action处理数据后,跳转页面 





第三种



编写Action  继承ActionSupport  (推荐)

   在Action中使用 表单校验、错误信息设置、读取国际化信息 三个功能





Action的配置method(通配符)



1) 在配置  元素时,没有指定method属性, 默认执行 Action类中 execute方法

2)使用通配符* ,简化struts.xml配置



<a href="${pageContext.request.contextPath }/user/customer_add.action">添加客户</a> 
  
<a href="${pageContext.request.contextPath }/user/customer_del.action">删除客户</a>

struts.xml
<action name="customer_*" class="cn.itcast.struts2.demo4.CustomerAction" method="{1}"></action>   ---  {1}就是第一个* 匹配内容




动态方法调用



访问Action中指定方法,不进行配置 

   1) 在工程中使用 动态方法调用 ,必须保证 struts.enable.DynamicMethodInvocation = true 常量值 为true 

   2) 在action的访问路径 中 使用 “!方法名”



页面 
  
<a href="${pageContext.request.contextPath }/user/product!add.action">添加商品</a>
配置
<action name="product" class="cn.itcast.struts2.demo4.ProductAction"></action>
执行 ProductAction 中的 add方法




Action访问Servlet API





1、 在Action 中解耦合方式 间接访问 Servlet API  ——— 使用 ActionContext 对象



在struts2 中 Action API 已经与 Servlet API 解耦合 (没有依赖关系 )

* Servlet API 常见操作 : 表单提交请求参数获取,向request、session、application三个范围存取数据



actionContext = ActionContext.getContext();

1) actionContext.getParameters(); 获得所有请求参数Map集合 

2) actionContext.put(“company”, “传智播客”); / actionContext.get(“company”) 对request范围存取数据 

3) actionContext.getSession(); 获得session数据Map,对Session范围存取数据

4) actionContext.getApplication(); 获得ServletContext数据Map,对应用访问存取数据





2、 使用接口注入的方式,操作Servlet API (耦合)



1.要求action类必须实现提定接口。

ServletContextAware : 注入ServletContext对象

ServletRequestAware :注入 request对象

ServletResponseAware : 注入response对象



2.重定接口中的方法。

private HttpServletRequest request;

3.声明一个web对象,使用接口中的方法的参数对声明的web对象赋值.



public void setServletRequest(HttpServletRequest request) { 
  
    this.request = request;
}




3、 在Action中直接通过 ServletActionContext 获得Servlet API



ServletActionContext.getRequest() : 获得request对象 (session)

ServletActionContext.getResponse() : 获得response 对象

ServletActionContext.getServletContext() : 获得ServletContext对象 

ServletActionContext.getPageContext().getSession(); //获取session等对象





Action处理请求参数





第一种 :Action 本身作为model对象,通过成员setter封装 (属性驱动 )





    页面: 
  
        用户名  <input type="text" name="username" />
    Action :
        public class RegistAction1 extends ActionSupport {
            private String username;
            public void setUsername(String username) {
                this.username = username;
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9




第二种 :创建独立model对象,页面通过ognl表达式封装 (属性驱动)





    页面: 
  
        用户名  <input type="text" name="user.username" />----- 基于OGNL表达式的写法
    Action:
        public class RegistAction2 extends ActionSupport {
            private User user;
            public void setUser(User user) {
                this.user = user;
            }

            public User getUser() {
                return user;
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13




使用ModelDriven接口,对请求数据进行封装 (模型驱动 ) —– 主流





    页面: 
  
        用户名  <input type="text" name="username" /> <br/>  
    Action :
        public class RegistAction3 extends ActionSupport implements ModelDriven<User> {
            private User user = new User(); // 必须手动实例化
            public User getModel() {
                return user;
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9




封装数据到Collection和Map



1) 封装数据到Collection 对象 

    页面:





    产品名称 <input type="text" name="products[0].name" /><br/> 
  
    Action :
        public class ProductAction extends ActionSupport {
            private List<Product> products;

            public List<Product> getProducts() {
                return products;
            }

            public void setProducts(List<Product> products) {
                this.products = products;
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13


2) 封装数据到Map 对象 

    页面:





        产品名称 <input type="text" name="map['one'].name" /><br/>  =======  one是map的键值 
  
    Action :
        public class ProductAction2 extends ActionSupport {
            private Map<String, Product> map;

            public Map<String, Product> getMap() {
                return map;
            }

            public void setMap(Map<String, Product> map) {
                this.map = map;
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13




请求参数校验





手工代码校验请求参数



步骤一: 封装数据 

步骤二: 实现校验Action ,必须继承ActionSupport 类 

步骤三: 覆盖validate方法,完成对Action的业务方法 数据校验通过代码逻辑判断参数是否有效,如果参数非法 , this.addFieldError (ActionSupport提供)workflow拦截器 跳转回 input页面

步骤四: 在jsp中 通过 s:fieldError 显示错误信息

validate方法会对Action中所有业务方法进行校验,如果只想校验某一个方法   : validate方法名()





Xml配置方式数据校验



位置:xml文件要与action类在同一个包下

名称:action类名-validation.xml(针对某个方法效验UserAction-regist-validation.xml)





    <?xml version="1.0" encoding="UTF-8"?> 
  
    <!DOCTYPE validators PUBLIC
            "-//Apache Struts//XWork Validator 1.0.3//EN"
            "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">


    <validators>
        <!-- 对username属性进行校验 -->
        <field name="username">
            <!-- 指定username不能为空 -->
            <field-validator type="requiredstring">
                <!-- 错误信息 -->
                <message>用户名不能为空--------</message>
            </field-validator>
            <!-- 长度校验,规定用户名必须在6-10位之间 -->
            <field-validator type="stringlength">
                <param name="maxLength">10</param>
                <param name="minLength">6</param>
                <message>用户名必须在${minLength}-${maxLength}位之间</message>
            </field-validator>
        </field>

        <!-- 对age进行校验,规定年龄必须在10-40之间 -->
        <field name="age">
            <field-validator type="int">
                <param name="min">10</param>
                <param name="max">40</param>
                <message>年龄必须在${min}--${max}之间</message>
            </field-validator>
        </field>

        <!-- 对birthday进行校验 -->
        <field name="birthday">
            <field-validator type="date">
                <param name="min">1974-01-01</param>
                <param name="max">2004-12-31</param>
                <message>生日必须在${min}年到${max}年之间</message>
            </field-validator>
        </field>

        <!-- 校验邮箱 -->
        <field name="email">
            <field-validator type="email">
                <message>邮箱格式不正确</message>
            </field-validator>
        </field>

        <!-- url校验 -->

        <field name="url">
            <field-validator type="url">
                <message>url不能这空,类似于http://www.baidu.com</message>
            </field-validator>
        </field>

        <!-- 使用正则 -->
        <field name="telphone">
            <field-validator type="regex">
                <param name="regexExpression"><![CDATA[^135[0-9]{8}$]]></param>
                <message>电话号码必须是135xxxxxxxx</message>
            </field-validator>
        </field>

        <field name="repassword">
            <field-validator type="fieldexpression">
                <param name="expression"><![CDATA[(password==repassword)]]></param>
                <message>两次密码输入不一致</message>
            </field-validator>
        </field>

    </validators>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70


内建校验器

* required (必填校验器,要求被校验的属性值不能为null)

* requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)

* stringlength (字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)

* regex (正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)

* int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)

* double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)

* fieldexpression (字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)

* email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址)

* url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址)

* date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)





Result结果类型



Action处理请求后, 返回字符串(逻辑视图名), 需要在struts.xml 提供 元素定义结果页面 

1、 局部结果页面 和 全局结果页面





    <action name="result" class="cn.itcast.struts2.demo6.ResultAction"> 
  
                <!-- 局部结果  当前Action使用 -->
                <result name="success">/demo6/result.jsp</result>
    </action>

    <global-results>
                <!-- 全局结果 当前包中 所有Action都可以用-->
                <result name="success">/demo6/result.jsp</result>
    </global-results>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9


2、 结果页面跳转类型 

    result标签

1.name  与action中的method的返回值匹配,进行跳转.

2.type  作用:是用于定义跳转方式



dispatcher:它代表的是请求转发,也是默认值。它一般用于从action跳转到页面。

chain:它也相当于请求转发。它一般情况下用于从一个action跳转到另一个action。



<!--hello是一个Action的name--> 
  
<result name="success" type="chain">hello</result>


redirect:它代表的是重定向  它一般用于从action跳转到页面

redirectAction: 它代表的是重定向  它一般用于从action跳转另一个action。



<result name="success" type="redirectAction">hello</result> 
  


stream:代表的是服务器端返回的是一个流,一般用于下载。





在jsp中显示错误信息





    <s:fieldError/> 
  
    <s:fielderror fieldName="">展示特定名称的错误信息.
  • 1
  • 2
  • 1
  • 2




Struts2国际化





资源文件编写



properties文件命名 :  基本名称语言(小写)国家(大写).properties

编写3个property文件



message.properties



name=tom 
  


messages_zh_CN.properties //中国中文



name=汤姆 
  


messages_en_US.properties //美国英文



name=tom 
  




资源文件作用域



1.针对于action类

位置:与action类在同一个包下.

名称:ActionClassName.properties.

这个配置文件只对当前action有效。



2.针对于package下所有action

位置:在指定的包下

名称:package.properties





怎样使用



1.在action类中使用

前提:action类要继承ActionSupport类。

getText(String name)就可以获取配置文件中对应名称的值。



2.在validation.xml文件中使用



<message key="名称"/> 
  


3.在jsp页面上使用



s:text name=”名称” 如果没有使用s:i18n name=”“来指定,会从全局配置文件中获取。

如果要从某一个配置文件中获取,通过name属性来指定,  包名.配置文件名称 .





    <s:i18n name="cn.itcast.action.package"> 
  
        <s:text name="nameerror"/>
    </s:i18n>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3




在struts2中国际化配置文件中使用动态文本



1.action中怎样使用



xxxx.property



msg=hello world  {0} 
  


action



this.getText("msg",new String[]{"tom"}) 
  


结果就是 hello world tom



2.jsp页面上怎样使用



xxxx.property

    msg=hello world  {0}



<s:i18n name="cn.itcast.action.I18nDemo1Action"> 
  
    <s:text name="msg">
        <s:param>张三</s:param>
    </s:text>
</s:i18n>


结果就是 hello world  张三





Struts2拦截器



struts2中在struts-default.xml文件中声明了所有的拦截器。

而struts2框架默认使用的是defaultStack这个拦截器栈。

在这个拦截器栈中使用了18个拦截器。简单说,struts2框架

在默认情况下,加载了18个拦截器。

注意:只要显示声明使用了一个拦截器。那么默认的拦截器就不在加载。





常用struts2 拦截器



<interceptor-ref name="modelDriven"/> 模型驱动 
  
<interceptor-ref name="fileUpload"/> 文件上传
<interceptor-ref name="params"> 参数解析封装
<interceptor-ref name="conversionError"/> 类型转换错误
<interceptor-ref name="validation"> 请求参数校验
<interceptor-ref name="workflow"> 拦截跳转 input 视图




自定义拦截器



struts.xml





<interceptors> 
  
    <interceptor name="my" class="cn.itcast.intercept.MyInterceptor">
    </interceptor>

    <interceptor name="bookInterceptor" class="cn.itcast.intercept.BookInterceptor">
        <param name="includeMethods">add,update,delete</param>
    </interceptor>

    <interceptor-stack name="myStack">
        <interceptor-ref name="bookInterceptor"></interceptor-ref>
        <interceptor-ref name="defaultStack" />
    </interceptor-stack>
</interceptors>

<action name="demo1" class="cn.itcast.action.Demo1Action">
    <result name="login">/login.jsp</result>
    <!-- <interceptor-ref name="my" /> <interceptor-ref name="defaultStack"/> -->
    <interceptor-ref name="myStack" />
</action>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19


action





public class BookInterceptor extends MethodFilterInterceptor { 
  

    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {

        // 1.得到session中的user
        User user = (User) ServletActionContext.getRequest().getSession().getAttribute("user");

        if (user == null) {
            BookAction action = (BookAction) invocation.getAction(); // 得到当前拦截的action对象。
            action.addActionError("权限不足,请先登录");// 存储错误信息
            return Action.LOGIN;
        }
        return invocation.invoke();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16




OGNL表达式和值栈



关于valueStack内部结构详解URL

http://blog.csdn.net/qq32933432/article/details/51568939





值栈在开发中应用





主流应用 : 值栈 解决 Action 向 JSP 传递 数据问题





Action 向JSP 传递数据处理结果 ,结果数据有两种形式





1) 消息 String类型数据





this.addFieldError("msg", "字段错误信息"); 
  
this.addActionError("Action全局错误信息");
this.addActionMessage("Action的消息信息");
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3



  • fieldError 针对某一个字段错误信息 (常用于表单校验)、actionError (普通错误信息,不针对某一个字段 登陆失败)、 actionMessage 通用消息  



在jsp中使用 struts2提供标签 显示消息信息





<s:fielderror fieldName="msg"/> 
  
<s:actionerror/>
<s:actionmessage/>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3




2) 数据 (复杂类型数据)



使用值栈





valueStack.push(products);
  • 1
  • 1


哪些数据默认会放入到值栈 ??? 

    1)每次请求,访问Action对象 会被压入值栈 ——- DefaultActionInvocation 的 init方法 stack.push(action);

    * Action如果想传递数据给 JSP,只要将数据保存到成员变量,并且提供get方法就可以了 

    2)ModelDriven 接口 有一个单独拦截器 

    

    在拦截器中 ,将model对象 压入了 值栈 stack.push(model);

    * 如果Action 实现ModelDriven接口,值栈默认栈顶对象 就是model对象





OGNL表达式 常见使用





、 % 、$ 符号使用



1) # 的 使用





用法一  # 代表 ActionContext.getContext() 上下文



  <s:property value="#request.name" />  ------------>  ActionContext().getContext().getRequest().get("name"); 
  


#request

  #session

  #application

  #attr

  #parameters





用法二 : 不写# 默认在 值栈中root中进行查找



   <s:property value="name" /> 在root中查找name属性 
  



  • 查询元素时,从root的栈顶元素 开始查找, 如果访问指定栈中元素  



    <s:property value="[1].name" />  访问栈中第二个元素name属性 
      

  • 访问第二个元素对象



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





用法三 :进行投影映射 (结合复杂对象遍历 )





1)集合的投影(只输出部分属性


遍历集合只要name属性





<s:iterator value="products.{name}" var="pname"> 
  
    <s:property value="#pname"/>
</s:iterator>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3




2)遍历时,对数据设置条件


遍历集合只要price大于1500商品





<s:iterator value="products.{?#this.price>1500}" var="product"> 
  
    <s:property value="#product.name"/> --- <s:property value="#product.price"/>    
</s:iterator>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3




3)综合


只显示价格大于1500 商品名称





<s:iterator value="products.{?#this.price>1500}.{name}" var="pname"> 
  
    <s:property value="#pname"/>
</s:iterator>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3




用法四: 使用#构造map集合



经常结合 struts2 标签用来生成 select、checkbox、radio

使用#构造map集合 遍历





<s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry"> 
  
    key : <s:property value="#entry.key"/> , value:  <s:property value="#entry.value"/> <br/>
</s:iterator>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3


2) %的使用 

<s:property value="表达式"> 对于s:property标签,它的value属性会被默认做为ognl.

   用法一: 结合struts2 表单使用, 通过%通知struts, %{}中内容是一个OGNL表达式,进行解析



   <s:textfield name="username" value="%{#request.username}"/> 
  


用法二: 设置ognl表达式不解析 %{‘ognl表达式’}



   <s:property value="%{'#request.username'}"/> 
  


3)$的使用 

   用法一 :用于在国际化资源文件中,引用OGNL表达式 在properties文件 msg=欢迎您${#request.username}

    在页面



    <s:i18n name="messages"> 
  
        <s:text name="msg"></s:text>
    </s:i18n>
    * 自动将值栈的username 结合国际化配置信息显示


用法二 :在Struts 2配置文件中,引用OGNL表达式



    <!-- 在Action 提供 getContentType方法 --> 
  
    <param name="contentType">${contentType}</param>


{contentType} 读取值栈中contentType数据,在Action提供 getContentType 因为Action对象会被压入值栈, contentType是Action属性,从值栈获得



结论: #使用ognl表达式获取数据,% 控制ognl表达式是否解析 ,$ 用于配置文件获取值栈的数据





使用OGNL访问 对象方法 和 静态方法



OGNL 在jsp 结合 struts2 标签库 使用 , <s:property value="ognl表达式" /> 执行 ognl表达式 

调用 实例方法 : 对象.方法()  —- <s:property value="'hello,world'.length()"/> 

调用 静态方法 : @[类全名(包括包路径)]@[方法名]  — <s:property value="@java.lang.String@format('您好,%s','小明')"/>

使用 静态方法调用 必须 设置 struts.ognl.allowStaticMethodAccess=true





Struts2 防止表单重复提交



1、 在jsp 通过 <s:token /> 生成令牌号 

生成表单隐藏域

将令牌号保存到Session



2、 通过struts2 提供 tokenIntercetor 拦截器 完成请求中令牌号 和 session中令牌号 比较





<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/> 
  
    <action name="token" class="cn.itcast.struts2.TokenAction">
        <result>/index.jsp</result>
        <!-- 重新定义拦截器 -->
        <interceptor-ref name="defaultStack"></interceptor-ref>
        <interceptor-ref name="token"></interceptor-ref>
    </action>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7


3、 当表单重复提交时,token拦截器自动跳转 result name=”invalid.token”

 通过  显示错误信息



覆盖重复提交信息  struts.messages.invalid.token=您已经重复提交表单,请刷新后重试



Struts2 内置json插件





1.导入json插件包



在struts2的lib包下  struts2-json-plugin-2.3.15.1.jar。 
  




2.在struts.xml文件中配置



1.<package extends="json-default"> 
  
2.设置视图<result type="json">


这样设置后,会将valueStack栈顶数据变成json。

对于我们的程序,也就是会将action对象转换成json。





设置只将指定的数据转json



<param name="root">p</param> 
  


如果没有设置,可以理解成将整个action都转换成json的数据。也就是

 在action中提供的getXxx方法,就是json中的一个属性。

如果设置了root,那么,只将指定数据转换成json.





怎样设置转换成json的对象中不包含特定的属性?




  1. @JSON(serialize=false) 在getXxx方法上设置

  2. 还可以通过json插件的interceptor完成.

    设置只展示products的name属性



    <param name="includeProperties">products\[\d+\]\.name</param> 
      


       
   

你可能感兴趣的:(java框架)