30-31Struts加强

1 拦截器

1.1 拦截器简介

拦截器  类似于  过滤器的功能,过滤器可以过滤项目的任何请求(servlet/jsp/html/img),但拦截器只能拦截Action资源。拦截完Action,添加逻辑代码

1.2 拦截器的编写规则

struts2提供Interceptor接口用于自定义拦截器

 

步骤:

1)编写类,实现Interceptor接口

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内起作用(interceptor-ref)

全局使用:当前包内起作用:(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的invocation.invoke()前面代码

4)执行inter2的invocation.invoke()前面代码

5Action的业务方法

6执行inter2的invocation.invoke()后面代码

7执行inter1的invocation.invoke()后面代码

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

这时需要这么做(拦截器栈的嵌套):

<interceptor-stack name="myStack">

  <interceptor-ref name="defaultStack"></interceptor-ref><!-- 引入了默认的18个拦截器 -->

  <interceptor-ref name="interStack"></interceptor-ref><!-- 引入自定义的2个拦截器 -->

</interceptor-stack>

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

 

2值栈

2.1 Ognl表达式简介

OGNL表达式

       OGNLObject Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。

EL表达式: 获取域对象的数据。 不能存放数据,不能调用方法

Ognl表达式: 获取域对象的数据。  可以存放数据,可以调用方法。

OGNL的优势:

1、支持对象方法调用,如xxx.doSomeSpecial()

2、支持类静态的方法调用和值访问,表达式的格式:

    @[类全名(包括包路径)]@[方法名 |  值名],例如:

    @java.lang.String@format('foo %s', 'bar')

     或@tutorial.MyConstant@APP_NAME

3、支持赋值操作和表达式串联,如price=100, discount=0.8,

    calculatePrice(),这个表达式会返回80

4、访问OGNL上下文(OGNL context)和ActionContext

5、操作集合对象。

2.2 Ognl表达式核心OgnlContext对象

1)普通存取OgnlContext数据

OgnlContext context = new OgnlContext(); //1)创建一个OgnlContext对象

context.put("user", user);//2)user对象存入OgnlContext对象

User user2 = (User)context.get("user");//3)OgnlContext对象取出数据

2使用Ognl表达式取出OgnlContext的数据,如果是非根对象数据,那么使用#号去取

OgnlContext context = new OgnlContext();

context.put("user", user);//OgnlContext的非根对象 存数据

Object ognlObj = Ognl.parseExpression("#user.age");//表达式对象

Object result = Ognl.getValue(ognlObj, context, context.getRoot()); //获取数据方法

System.out.println(result);

3)往OgnlContext根对象存取数据,不需要使用#号,不需要key名称,直接写存入对象的属性即可!!!

OgnlContext context = new OgnlContext();

context.setRoot(user);////OgnlContext的根对象 存数据

Object ognlObj = Ognl.parseExpression("name");//Ognl表达式对象

Object result = Ognl.getValue(ognlObj, context, context.getRoot()); //获取数据方法

4Ognl表达式调用静态方法

//java.util.Math

OgnlContext context = new OgnlContext();

Object ognlObj = Ognl.parseExpression("@java.lang.Math@round(10.5)");//表达式对象(lang包可以只写类名)

Object result = Ognl.getValue(ognlObj, context, context.getRoot()); //获取数据方法

2.3 struts2的值栈(ValueStack)对象(利用OgnContext对象)

ValueStack接口,最终在项目中存储数据的对象是ValueStack的实现类OgnlValueStack

ValueStack的数据存储结构:分为List栈(根栈)和Map栈(非根栈)

1List栈主要存储Action对象和Provider代理对象

2Map栈主要存放各个域存放的数据和用户的参数信息

 

 * 在用户每次访问action对象的业务方法时,struts2框架会创建ActionContext对象 (OgnlValueStack对象(Action对象))

1)往域对象存放数据(非根栈)

ac.getContextMap().put("request_data", "data");

ac.getSession().put("session_data", "data");

ac.getApplication().put("application_data", "data");

2)向List存取数据(根栈)

注:定义了JavaBean结构,就会在List栈中显示,可以直接在页面获取,用Push会增加对象。

//1)获取ActionContext对象

ActionContext ac = ActionContext.getContext();

ac.getContextMap().put("userList", list);

//2)从ActionContext对象获取OnglValueStack对象

ValueStack vs = ac.getValueStack();

//3)往OgnlValueStack的根对象(List栈)存放数据

vs.push(user);//往Lis栈存放数据(栈顶)

vs.pop(); //从List栈中取出元素(栈顶元素)

 

 

2.4页面获取值栈(ValueStack)数据

<%@ taglib uri="/struts-tags" prefix="s"%><%-- 导入struts2标签 --%>

<%--查看值栈的所有数据 --%>

<s:debug></s:debug><br/>

<%-- 1)取出List栈的数据 --%>

<s:property value="user.name"/> <br/>

<%--2)取出Map栈的数据 --%>

<s:property value="#request.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/>

<%-- 遍历集合 :List、Map--%>

<s:iterator value="#request.userList" var="user">

姓名: <s:property value="#user.name"/> - <s:property value="#user.age"/><br/>

</s:iterator>

3数据验证

struts2提供给开发者进行表单数据的后台数据验证的功能。

3.1 用代码方式对action的所有方法进行验证

struts2的数据验证的核心拦截器(jar包内已注册)

<interceptor name="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>

开发步骤:

1Action类继承ActionSupport(为了实现Valiateable接口)

2Action类覆盖validate方法(验证所有方法)

  * 如果validate方法中出现异常,那么把错误信息放入错误信息Map集合,就直接返回错误页面

  super.addFieldError("user.error.requried", "用户名不能为空!");

  * 如果validate没有出现异常,那么直接运行业务方法(register)

3)在struts.xml文件中对应的action配置加上input视图,然后struts2就会自动把错误信息转发到input视图的页面上去

<result name="input">/register.jsp</result>

4)在input视图页面上,打印出错误信息

<s:fielderror></s:fielderror>

注意:

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

3.2 用代码方式对action的指定方法进行验证

第二步骤的验证方法名称为  validate+需要验证的方法名称

例如: validateRegister()   ->  可以验证register()方法

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

xml配置数据验证的规则:

1)编写一个xml文件,名称:  Action文件名-validation.xml

2)该xml文件必须放在Action文件的同一目录

注意: 这种配置方式会对action下的所有方法都生效!!!

3.4 xml配置方式对action的指定方法进行验证

xml配置数据验证的规则:

1)编写一个xml文件,名称: Action文件名-访问方法路径-validation.xml

例如: UserActionregister方法: user_register路径访问

文件名:   UserAction-user_register-validation.xml

2)该xml文件必须放在Action文件的同一目录

<validators>

  <!-- 验证用户名 -->

  <field name="user.name">(Action中需要验证的属性名称)

     <!-- type: 代表xwork中定义的可以使用的验证类型 -->

    <field-validator type="requiredstring">(验证类型)

     <!-- 当出现错误时,提示的错误信息 -->

     <message>用户名必填</message>(出现之后页面显示的信息)

    </field-validator>

    <field-validator type="stringlength">

     <param name="minLength">6</param>(注入到验证类型类中的属性)

     <param name="maxLength">16</param>

<!-- 注入正则的字符串 -->

     <param name="expression">^[a-zA-Z0-9]{4,12}$</param>

     <message>用户名必须是6-16</message>

    </field-validator>

  </field>

</validators>

验证类型:

name="required" 

name="requiredstring" 

name="int" 

name="long" 

name="short" 

name="double"

name="date"

name="expression"

name="fieldexpression"

name="email"

name="url"

name="visitor"

name="conversion"

name="stringlength" name="regex" 

name="conditionalvisitor" 

4 struts2中简化国际化的使用

1)准备不同国家的资源包

中国: message_zh_CN.propertiesuser=用户名)

美国: message_en_US.properties user=username)

英国:  message_en_GB.properties

 

2)在struts.xml文件中(修改)指定资源包加载路径的常量

struts.custom.i18n.resources=message

<constant name="struts.custom.i18n.resources" value="resources.message"></constant>

 

3)在页面上使用资源包的内容

  <s:text name="user"></s:text>

4)在程序中获取内容

action.getText("user");

5 防止页面的重复提交

默认情况下,struts2不支持防止重复提交的

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

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

<interceptors>

<interceptor-stack name="myStack">

<interceptor-ref name="defaultStack"></interceptor-ref>

<interceptor-ref name="token"></interceptor-ref>

</interceptor-stack>

</interceptors>

//当重复提交的时跳转页面

<result name="invalid.token">/model.jsp</result>

2)在jsp页面表单内指定一个标签:<s:token></s:token>

6 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>

posted @ 2018-05-10 10:26  风拂生  阅读(125)  评论(0编辑  收藏  举报