struts2(2)

struts2(2)

整理了从开始学习Java以来在纸质本上做的一些笔记,如有错误,恳请批评指正。


1 拦截器

1.1 拦截器简介
拦截器 类似于 过滤器的功能,过滤器可以过滤项目的任何请求(servlet/jsp/html/img),但拦截器只能拦截Action资源。拦截完Action,添加逻辑代码
1.2 拦截器的编写规则
struts2提供Interceptor接口用于自定义拦截器

步骤:
1)编写类,实现Interceptor接口

public class MyInterceptor1 implements Interceptor{

    public MyInterceptor1(){
        System.out.println("1)创建了拦截器1对象");
    }

    public void destroy() {

    }

    public void init() {
        System.out.println("2)调用了拦截器1的init方法");
    }

    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("4)拦截了Action---前面的代码");

        //放行,调用下一个拦截器,如果没有下一个拦截器,那么调用目录的action
        invocation.invoke();

        System.out.println("6)拦截了Action---后面的代码");

        return null;
    }

}

2)在struts.xml文件中定义和使用拦截器

<package name="inter" extends="struts-default" namespace="/inter">
    <!-- 定义拦截器 -->
    <interceptors>
        <interceptor name="inter1" class="gz.itcast.a_interceptor.MyInterceptor1"></interceptor>
    </interceptors>

    <action name="user_*" class="gz.itcast.a_interceptor.UserAction" method="{1}">
        <!-- 使用拦截器 -->
        <interceptor-ref name="inter1"></interceptor-ref>
        <result>/index.jsp</result>
    </action>

</package>

注意1:拦截器的执行顺序:
启动:
1)拦截器对象创建,调用拦截器的init方法
访问
2)创建Action对象
3)执行拦截器的intercepot方法
3.1 执行拦截器前面的代码(invocation.invoke();方法之前的)
3.2 执行 invocation.invoke(); 放行执行下一个拦截器或Action的方法
3.3 执行拦截器后面的代码(invocation.invoke();方法之后的)

注意2:拦截器范围:
局部使用:action其作用

<action name="user_*" class="gz.itcast.a_interceptor.UserAction" method="{1}">
        <!-- 局部起作用的使用拦截器 -->
        <interceptor-ref name="inter1"></interceptor-ref> 
        <result>/index.jsp</result>
</action>

全局使用: 当前包其作用:

<package name="inter" extends="struts-default" namespace="/inter">
            <!-- 定义拦截器 -->
            <interceptors>
                <interceptor name="inter1" class="gz.itcast.a_interceptor.MyInterceptor1"></interceptor>
            </interceptors>

            <!-- 全局其作用的拦截器 -->
            <default-interceptor-ref name="inter1"></default-interceptor-ref>

1.3 拦截器栈
概念: 当一个或多个Action同时被多个拦截器所拦截,就可以使用拦截器栈。

<interceptors>
    <interceptor name="inter1" class="gz.itcast.a_interceptor.MyInterceptor1"></interceptor>
    <interceptor name="inter2" class="gz.itcast.a_interceptor.MyInterceptor2"></interceptor>
    <!-- 定义栏截器栈 -->
    <interceptor-stack name="interStack">
        <interceptor-ref name="inter1"></interceptor-ref>
        <interceptor-ref name="inter2"></interceptor-ref>
    </interceptor-stack>
</interceptors>

注意1:定义拦截器栈的时候,引用拦截器的顺序决定了创建拦截器对象的顺序。(先指定就先创建)

注意2: 当前有了拦截器栈(多个拦截器)的执行顺序:
启动:
1)创建拦截器inter1对象,调用init方法
2)创建拦截器inter2对象,调用init方法

访问:
3)执行inter1的interceptor方法前面代码
4)执行inter2的interceptor方法前面代码
5)Action的业务方法
6)执行inter2的interceptor方法后面代码
7)执行inter1的interceptor方法前面代码

注意3: 当我们的包下引用了自定以拦截器,则会把默认包下的default-stack拦截器给覆盖掉!!!
这时需要这么做:

<interceptor-stack name="myStack">
    <interceptor-ref name="defaultStack"></interceptor-ref><!-- 引入了默认的18个拦截器 -->
    <interceptor-ref name="interStack"></interceptor-ref><!-- 引入自定义的2个拦截器 -->
</interceptor-stack>

struts2的核心流程图(关键):

enter image description here

OGNL表达式:
参考:
el表达式跟ognl表达式的区别:http://www.cnblogs.com/ycxyyzw/p/3493513.html
Struts2学习笔记:http://www.cnblogs.com/Cratical/archive/2012/09/09/2677909.html

结论:
1)从OgnlContext对象的根对象取出数据,不需要#号
2)从OgnlContext对象的非根对象取出数据,需要#号

Ognl表达式核心—>OgnlContext对象(Map结构)

存数据:*OgnlContext context = new OgnlContext();
1. 往OgnlContext的非根对象存数据: context.put("key",value);
2. 往OgnlContext的根对象存储数据:context.setRoot(对象);
取数据:
1. 非根数据,取出用#加key。因为非根数据是map结构存储。
2. 根对象数据,不需#,不需要key,直接写存入对象的属性名即可。

struts2的值栈(ValueStack对象)利用了(OgnlContext对象)

ValueStack接口:实现类对象OgnlValueStack

创建action对象会同时创建值栈对象。

ValueStack的数据存储结构:List栈(根数据)、Map栈(非根)
1. List栈主要存储action对象和provider对象。
2. Map栈主要存放各个域存放的数据和用户的参数信息。

List栈:从栈顶搜索,同名取第一个。

使用struts2的标签结合Ognl表达式获取值栈数据:

<%-- 1)取出List栈的数据 --%>
  <s:property value="user.name"/> - <s:property value="user.age"/> <br/>
    <s:property value="book.user.name"/> - <s:property value="name"/>
    <%--查看值栈的所有数据 --%>
    <hr/>
    <%--2)取出Map栈的数据 --%>
    <s:property value="#request.request_data"/><br/>
    <%-- 因为值栈对象是通过request域专递到页面,所以可以直接忽略#request去取request域的数据 --%>
    <s:property value="#request_data"/><br/>
    <s:property value="#session.session_data"/><br/>
    <s:property value="#application.application_data"/><br/>
    <%-- #attr : 类似于findAttribute. 依次从小到大在三个域中搜索数据:  #request-> #session -> #application --%>
    <s:property value="#attr.session_data"/><br/>
    <s:property value="#parameters.name"/><br/>
    <hr/>
    ${session_data }
    <hr/>
    <%-- 遍历集合 :List--%>
    <s:iterator value="#request.userList" var="user">
        姓名: <s:property value="#user.name"/> - <s:property value="#user.age"/><br/>
    </s:iterator>
    <hr/>
     <%-- 遍历集合:Map --%>
    <s:iterator value="#request.userMap" var="entry">
        编号: <s:property value="#entry.key"/> - 姓名: <s:property value="#entry.value.name"/> - <s:property value="#entry.value.age"/><br/>
    </s:iterator>
    <s:debug></s:debug>

因为值栈对象是通过request域传递到页面的,所以可以忽略#request直接从request域中取值。

思考:放在request中的值栈可以存储session和context域数据,显然request的作用域没这么大,威慑呢么?
值栈中的是引用,其生命周期贯穿Action对象始终。

当struts2接受到一个访问时,迅速创建ActionContext、ValueStack、和Action对象。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。

“#号的作用:除了用于查询非根数据外,还可以在JSP页面中构建Map集合。

%的作用:用于通知执行环境%{}里面的是OGNL表达式。为确保安全可在任何地方都使用%{}。

更多的使用参考:
Struts标签、Ognl表达式、el表达式、jstl标签库这四者之间的关系和各自作用:http://blog.youkuaiyun.com/love_you_99/article/details/8184797

OGNL表达式原理:http://developer.51cto.com/art/201203/322509.htm

2 数据验证

2.1 用代码方式对action的所有方法进行验证
struts2的数据验证的核心拦截器:
<interceptor name="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>

开发步骤:
1)Action类继承ActionSupport(为了实现Valiateable接口)
2)Action类覆盖validate方法(验证所有方法)
3)在struts.xml文件中对应的action配置加上input视图,然后struts2就会自动把错误信息转发到input视图的页面上去
4)在input视图页面上,打印出错误信息


public void validate() {
        //在这里写表单数据验证的逻辑
        //System.out.println("调用了validate方法");
        if(user.getName()==null || user.getName().equals("")){
            //用户名为空
            //把错误信息放入错误信息Map集合
            super.addFieldError("user.error.requried", "用户名不能为空!");
        }
        if(user.getPassword()==null || user.getPassword().equals("")){
            //密码为空
            //把错误信息放入错误信息Map集合
            super.addFieldError("password.error.requried", "密码不能为空!");
        }

    }

<s:fielderror></s:fielderror>打印错信息

注意:
validate()方法对当前Action下的所有方法都会有效!!!!

2.2 用代码方式对action的指定方法进行验证
指定方法验证:
第二步骤的验证方法名称为 validate+需要验证的方法名称
例如: validateRegister() -> 可以验证register()方法

2.3 用xml配置方式对action的所有方法进行验证

xml配置数据验证的规则:
1)编写一个xml文件,名称: Action文件名-访问方法路径-validation.xml
例如: UserAction的register方法: user_register路径访问
文件名: UserAction-user_register-validation.xml
2)该xml文件必须放在Action文件的同一目录

<validators>
  <!-- 验证用户名 -->
  <field name="user.name">
     <!-- type: 代表xwork中定义的可以使用的验证类型 -->
     <field-validator type="requiredstring">
        <!-- 当出现错误时,提示的错误信息 -->
        <message>用户名必填</message>
     </field-validator>
     <field-validator type="stringlength">
        <param name="minLength">6</param>
        <param name="maxLength">16</param>
        <message>用户名必须是6-16位</message>
     </field-validator>
  </field>

 <field-validator  type="email"/>
 <field-validator type="regex"/>

</validators>   

3 模型驱动

请求数据封装:
方式一: 表单: name -》 基本数据类型: String name
方式二: 表单: user.name - 》 javabean数据类型: User user (User: String name)

方式三: 表单: name -> javabean数据类型: User user (User: String name) (使用模型驱动方式)

public class UserAction extends ActionSupport implements ModelDriven<User>{
    //注意:使用模型驱动的方式,存放数据的模型引用不能为空
    private User user = new User();

    /**
     * 该方法struts2可以把值栈中的请求参数封装到User对象
     */
    public User getModel() {
        return user;
    }   
}

注意:
1. 存放数据的模型引用不能为空,即必须new。
2. setter和getter不能少。

4 常用的struts2的标签

4.1 Ognl常用的符号
1) { } 创建List

    <%-- ognl表达式: 在jsp页面中创建List集合(不需要#) --%>
    <s:iterator value="{'eric','jacky','rose','lucy'}" var="name">
        <s:property value="#name"/><br/>
    </s:iterator>

2) #{ } 创建Map集合

    <%-- ognl表达式: 在jsp页面中创建Map集合(需要#号) --%>
    <s:iterator value="#{1:'eric',2:'jacky',3:'rose',4:'lucy'}" var="entry">
        编号: <s:property value="#entry.key"/>-姓名:<s:property value="#entry.value"/><br/>
    </s:iterator>  

3)%{ } 把内容引入Ognl运行环境

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

4.2 常用的逻辑标签


<body>

    <s:set var="变量名" scope="放置的范围,接受application,session,page,action" value="值"></s:set>

    <s:bean name="JavaBean全名" var="被赋值的对象名,不设置则放置在栈顶"></s:bean>

    <!-- 逻辑标签 -->
    迭代:<s:iterator value="ognl表达式"></s:iterator>

    赋值:<s:set var="" value=""></s:set>

    获取:<s:property value="ognl表达式"/>

    判断:<s:if test=""></s:if>


    <!-- UI标签 -->
    <!-- 优点
    1. 节省html代码
    2. 数据回显功能!!!!!!!
     -->
    <s:form></s:form>
    <s:text name=""></s:text>
    <s:textfield></s:textfield>
    <s:password></s:password>
    <s:checkboxlist list=""></s:checkboxlist>
    <s:radio list=""></s:radio>
    <s:select list=""></s:select>
  </body>

4.3 表单数据回显
struts2标签自带回显功能

4.4 放在页面的重复提交
默认情况下,struts2不支持防止重复提交的

1)需要在struts.xml文件中打开功能:

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

2)在jsp页面指定一个标签
<s:token></s:token>标记此页面不可重复提交。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值