struts2知识点总结


 

 


 

什么是框架

         框架是一种结构化的软件,框架尽量将特定领域的日常任务和具体问题的处理流程抽象化,然后提供一个平台,基于这个平台更快的构建web应用程序。

两个方面:尽量自动化web应用程序开发过程中的常见问题;尽量提供优秀的架构解决方案来优化web应用程序中常见的工作流。

 

 


struts2工作原理

 

使用xml和注解两种方式声明一个action

<action name=’login’>

         <resultname=”success”>/myPg.jsp</result>

         <resultname=”error”>/error.jsp</result>

</action>

@Results({@Result(name=”success”,value=”/myPg.jsp”),

                  @Result(name=”error”,value=”/error.jsp”)

})

public class Login

{

         … …

}

 

 

web.xml中配置struts2

<filter>

         <filter-name>struts2</filter-name>

         <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

actionPackages用于启用注解

告诉struts2在哪里查找注解

         <init-param>

                  <param-name>actionPackages</param-name>

                  <param-value>com.aowin</param-value>

         </init-param>

</filter>

 

<filter-mapping>

struts2拦截的url请求

         <filter-name>struts2</filter-name>

         <url-pattern>/*</url-pattern>

</filter-mapping>

 

 

 

 

 

 

 

 

 

 

一个典型的struts.xml文件

<?xml version="1.0"encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC

   "-//Apache Software Foundation//DTD Struts Configuration2.1.7//EN"

   "http://struts.apache.org/dtds/struts-2.1.7.dtd">

   

<struts>

                  <!—常量调整struts属性,开发者模式 -->

         <constantname=”struts.devMode” value=”true”/>

           

                  <!--action由包来管理的 -->

            <packagename="deafult" namespace="/"extends="struts-default">

            <!-- actionname与请求的名字是一致,actionclass与处理请求的action的类一致的默认执行actionexecute方法-->

                     <actionname="login" class="com.aowin.action.LoginAction">

                     <!--result表示方法的处理结果,name与逻辑视图对应

                        result的内容部分表示物理视图-->

                             <resultname="success">hello.jsp</result>

                     </action>

            </package>

 

                  <!—将其他的xml文档包含进此根文档-->

                  <includefile=”com/aowin/xxx.xml”/>

   </struts>

 

struts.xml是在默认包内定义全局动作的好地方。

 

使用包的命名空间来决定映射到动作的url:

http:// +localhost:8080 + /myApplication + /namespace + /HelloWorld.action

 

 协议       主机名:端口  应用根目录/servlet上下文  包命名空间        动作名.action

 

 

 

 

 

 

从表单页面通过action再到结果页面数据的传递

提交表单的页面:

<%--引入struts标签--%>

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

 

<body>

         <p>

                  <%--struts标签来表示表单元素--%>

                  <s:formaction=”HelloWorld” /><%--HelloWorld是对应的action名称没有后缀--%>

                                   <s:textfiledname=”name” label=”Your name”/><name对应javaBean属性>

                                   <s:submit/>

                       </s:form>

    </p>

</body>

 

提交页面表单时,框架会将传入的数据设置到javaBean属性上,通过execute()方法可以访问、操作这些数据,并返回一个结果字符串来转发到另一个jsp页面。

action的动作java类

public class HelloWorld

{

         privatestatic final String GREETING=”Hello”;

         private Sringname;  //保存数据的JavaBean属性

         private StringcustromGreeting; //保存数据的JavaBean属性

        

        //要执行的动作的业务逻辑,action默认调用此方法

         public Stringexecute()

         {

                  setCustomGreeting(GREETING+getName());

                  return“success”;

         }

         //省略gettersetter方法

         …

         …

}

 

呈现结果的jsp页面代码片段获取传输的数据

<%--引入struts标签--%>

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

 

<body>

         <p>

                  <%--struts标签来接受javaBean属性中的数据--%>

                  <s:propertyvalue=”customGreeting”/>

    </p>

</body>

 

 

使用注解的方式来配置动作action:

1.     首先在web.xml配置初始化参数actionsPackages,参数指定了一个扫描包,框架会用此包名之后的包名称作为action的命名空间。比如指定了在com.aowin中扫描,而动作类在com.aowin.myAction包中。则命名空间就是myAction。

2.     Java类可以通过命名约定类名以Action结尾。来表明这是一个action动作类。或者通过实现Action接口(直接继承实现action接口的ActionSupport类亦可)。

事例如下:

@Result(name=”success”,value=”/helloWorld.jsp”) //指示动作结果页面

public class NameCollector extends ActionSupport

{

         。。。。。。

}

或者是

@Result(name=”success”,value=”/helloWorld.jsp”) //指示动作结果页面

public class NameCollectorAction   //在动作url请求中Action部分会被去除

{

         。。。。。。

}

 

 

 

 

 

 

struts.xml中包(package)的声明

<package></package>元素的属性:

属性

描述

name(必须)

包的名字

namespace

包内所用动作的命名空间

extends

被继承的父包

abstract

如果为true,这个包只能用了定义可继承的组件,不能定义动作

  

 

namespace空命名空间””和根命名空间”/”的区别

        默认的命名空间namespace="",根命名空间namespace="/"<package name="test" extends="struts-default"> ,如果未指定命名空间,则命名空间默认为namespace=""。
  默认命名空间里的Action可以处理任何命名空间下的Action请求。例如,如果存在URL为/barspace/bar.action的请求,并且/barspace的命名空间下没有名为bar的Action,则默认命名空间下名为bar的Action也会处理用户请求。但根命名空间下的Action只处理根命名空间下的Action的请求,这是根命名空间和默认命名空间的区别。
    命名空间只有一个级别。如果请求的URL是/bookservice/search/get.action,系统将先在/bookservice/search的命名空间下查找名为get的Action,如果在该命名空间内找到名为get的Action,则由该Action处理用户的请求;如果未找到,系统将直接进入默认的命名空间中查找名为get的Action,而不会在/bookservice的命名空间下查找名为get的Action.
 
 

Action接口

public interface Action {

    public static final String SUCCESS ="success";

    public static final String NONE ="none";

    public static final String ERROR ="error";

    public static final String INPUT ="input";

    public static final String LOGIN ="login";

    public String execute()throws Exception;

}


 

数据验证拦截器

ActionSupport类的声明如下:

publicclassActionSupportimplements Action, Validateable, ValidationAware,TextProvider, LocaleProvider, Serializable{}

 

action动作类扩展ActionSupport类,ActionSupport实现了validate()方法,我们用特定的验证逻辑覆盖这个空方法,当执行动作时会触发默认的拦截器workflow拦截器,它会调用找到的validate()方法。当验证不通过时会把请求工作流重新定向到输入页面。

workflow拦截器的定义如下:

<interceptor name=”workflow”class=”com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor”/>

 

事例如下:register的动作类

public class Register extends ActionSupport

{

       privateString username;

       privateString password;

       privateString bagName;

       privateUserService userService;   

 

       publicString execute()

       {

              Useruser=new User();

              user.setPassword(getPassword() );

              user.setBagName(getBagName() );

              user.setUsername(getUsername() );

              userService.insertUser(user);

              returnSUCCESS;

       }

      

  //数据验证业务逻辑,没有返回值

       public void validate()

       {

              if(getPassword().length()== 0)

                     {

                         /*addFieldError()用来创建和存储错误消息,拦截器会检查是否存在错误消息,若存在则表示验证失败,终止请求,选择为”input”的结果视图*/

                            addFieldError(“password”,”Password isrequired.”);

                     }

              if(getUsername().length()== 0)

                     {

                            addFieldError(“username”,”usernameis required.”);

                     }

              if(getBagName().length()==0)

                     {

                            addFiledError(“bagName”,”Bag name isrequired.”);

                     }

              if(userService.userExists(getUsername()))

                     {

                            addFieldError(“username”,”This useralready exists.”);

                     }

       }

       … …//省略其他setttergettter方法

}

 

 

使用资源包处理文本消息

需要创建属性文件,并且名字和动作类名相同,比如对应Register.java的属性文件可以命名为Register.properties.将属性文件和类放在一个包中。ActionSupport实现了方法来从属性文件中取得消息。

 

Register.properties内容如下:

user.exists=This user already exists.

username.required=Username is required.

password.required=Password is required.

bagName.required=Bag name is required.

 

上面的验证错误消息可以更改如下:

//数据验证业务逻辑,没有返回值

       public void validate()

       {

              if(getPassword().length()== 0)

                     {

                         /*addFieldError()用来创建和存储错误消息,拦截器会检查是否存在错误消息,若存在则表示验证失败,终止请求,选择为”input”的结果视图*/

                            addFieldError(“password”,getText(“password.required”));

                     }

              if(getUsername().length()== 0)

                     {

                            addFieldError(“username”,getText(“username.required”));

                     }

              if(getBagName().length()==0)

                     {

                            addFiledError(“bagName”,getText(“bagName.required”));

                     }

              if(userService.userExists(getUsername()))

                     {

                            addFieldError(“username”,getText(”user.exists”));

                     }

       }

 

接口com.opensymphony.xwork2.LocalProvider提供了一个方法getLocale(),可以根据地域设置本地化的消息字符串。ActionSupport实现了这个接口,并且会自动判断得到本地的属性文件。需要为当前地域提供属性文件。

属性文件命名为:类名_地域代码.properties。比如对应中国的消息文件可以设置为

Register_zh.properties.内容如下:

user.exists=此用户已存在。

username.required=用户名不能为空。

password.required=密码不能为空。

bagName.required=公文包名不能为空。

 

向对象传递数据

公开一个复杂对象作为javaBean属性,让数据传输到这个对象上。还有另一种选择就是使用ModelDriven动作(涉及一个接口和一个默认拦截器)。

对象支持的JavaBean属性

public class Register extends ActionSupport

{

       privateUser user; //User类包含username,password,bagName三个字段

       privateUserService userService;   

 

       publicString execute()

       {

              userService.insertUser(user);

              returnSUCCESS;

       }

      

  //数据验证业务逻辑,没有返回值

       public void validate()

       {

              if(getUser().getPassword().length()== 0)

                     {

                         /*addFieldError()用来创建和存储错误消息,拦截器会检查是否存在错误消息,若存在则表示验证失败,终止请求,选择为”input”的结果视图*/

                            addFieldError(“password”, getText(“password.required”));

                     }

              if(getUser().getUsername().length()== 0)

                     {

                            addFieldError(“username”, getText(“username.required”));

                     }

              if(getUser().getBagName().length()==0)

                     {

                            addFiledError(“bagName”, getText(“bagName.required”));

                     }

              if(userService.userExists(getUser().getUsername()))

                     {

                            addFieldError(“username”, getText(“user.exists”));

                     }

       }

       … …//省略其他setttergettter方法

}

 

 

再提交动作的表单中需要修改字段域的name属性:

<s:textfield name=”user.username” label=”Username”/>

 

结果页面也要用深层属性标记来进行访问数据:

<h3> hello,<s:property value=”user.username”/> </h3>

 

使用ModelDriven动作来实现对象数据传输

实现com.opensymphony.xwork2.ModelDriven接口,通过getModel()方法公开应用域对象。数据转移依然是自动化的。

 

 

public class Register extends ActionSupport implementsModelDriven

{

       //必须User进行对象初始化

       privateUser user=new User(); //User类包含username,password,bagName三个字段

       privateUserService userService;   

 

       publicString execute()

       {

              userService.insertUser(user);

              returnSUCCESS;

       }

      

       publicObject getModel()

       {

              return user;

       }

      

       … …

}

陷阱:若在动作内部execute()方法中改变模型字段,框架不会察觉,将导致数据不一致的问题。jsp结果页面会根据原始的引用对象求值,在方法内部新设置的对象值将无法访问。

 

 

在表单页面和结果页面不需要进行深层引用:

<s:textfield name=” username”label=”Username”/>

 

<h3> hello,<s:property value=” username”/></h3>

 

 

 

 

从页面表单数据到javaBean属性的传输与类型转换

内建的类型转换器:

String  boolean/Boolean  char/Character  int/Integer float/Float  long/Long 

double/Double  Date(当前Locale的SHORT格式的字符串版本如12/10/97)

array  List Map

当框架定位一个OGNL 表达式指向上述Java属性时,会自动完成类型的转换。

 


 

1.数组

指向javaBean数组字段的jsp表单字段:

<s:form action=”xx”>

这些字段指向ages属性

          <s:textfieldname=”ages” label=”Ages”/>

          <s:textfieldname=”ages” label=”Ages”/>

          <s:textfieldname=”ages” label=”Ages”/>

 

这些字段指向

names属性带索引

          <s:textfieldname=”names[0]” label=”names”/>

          <s:textfieldname=”names[0]” label=”names”/>

          <s:textfieldname=”names[0]” label=”names”/>

         

          <s:submit/>

</s:form>

请求进入框架时,共存在4个请求参数:

参数名

参数值

ages

12,33,102

names[0]

Chad

names[1]

Don

names[2]

Beth

 

执行的javaBean数组属性

private Double[] ages;

private String[] names=new String[10];

 

:表单中name属性带索引的数据参数,这种方法必须对数组进行初始化。

 

2.List

默认情况下,框架会把参数转换为String,并且填充到List属性中。

          <s:textfieldname=”middleNames[0]” label=”middleNames”/>

          <s:textfieldname=” middleNames[0]” label=”middleNames”/>

          <s:textfieldname=” middleNames[0]” label=”middleNames”/>

 

          <s:textfieldname=”lastNames” label=”lastNames”/>

          <s:textfieldname=”lastNames” label=”lastNames”/>

          <s:textfieldname=”lastNames” label=”lastNames”/>

 

来自于action动作类的List属性

private List lastNames;

private List middleNames;

注意:不需要初始化任何一个List。没有类型说明,List中的元素都是String。

为List中元素指定类型,可以使用泛型集合List<>.还可以通过一个简单的属性文件进行指定。属性文件命名约定:

ClassName-conversion.properties

ClassName:表示动作类名;-conversion:为类型转换属性文件的固定后缀。

         属性文件放在和类同一个包中。

         内容如下所示:

Element-middleNames=java.lang.String

                  Elementt-:为固定前缀;middleNames:为List类型属性的名字。

        

         指定List属性的元素类型为一个User类。

          <s:textfieldname=”users[0].username” label=”Usernames”/>

          <s:textfieldname=”users[1].username” label=”Usernames”/>

          <s:textfieldname=”users[2].username” label=”Usernames”/>

动作类的属性:

private List<User> users;

        

 

3.Map

Map对象必须提供一个键值,也可以为键值指定一个类型,否则默认为String.

<s:textfieldname=”maidenNames.mary.username” label=”username”/>

<s:textfieldname=”maidenNames.jane.username” label=”username”/>

<s:textfieldname= “maidenNames.hellen.username” label=”username”/>

 

<s:textfieldname=”maidenNames[‘beth’],birthday”  label=”birthday”/>

<s:textfieldname=”maidenNames[‘sharon’].birthday”  label=”birthday”/>

<s:textfieldname= “maidenNames[‘martha’].birthday”  label=”birthday”/>

 

 

为键和值指定类型:

Key_maidenNames=java.lang.String

Element_maidenNames=com.aowin.User

 

javaBean属性:

privateMap maidenNames;

 

强烈建议使用泛型集合。

 

 

 

自定义类型转换

我们可以自定义一个类型转换器来实现我们想要转换的任何java类型

比如将一个表单里的数据字符串:C:r15转换成Circle类对象其中15是半径

 

Circle类:

public class Circle

{

privatedouble radius;

 

… …

}

 

自定义类型转换器,需要实现StrutsTypeConverter接口。

public class CircleTypeConverter extendsStrutsTypeConverter

{

publicObject convertFromString(Map context,String[] values),Class toClass)

{

          StringuserString=values[0];

          CirclenewCircle=parseCircle(userString);

          returnnewCircle;

}

 

publicString convertToString(Map context,Object o)

{

          Circlecircle=(Circle)o;

          StringuserString=”C:r”+circle.getRadius();

          returnuserString;

}

 

privateCircle parseCircle(String userString) throws TypeConversionException

{

          Circlecircle=null;

          intradiusIndex=userString.indexOf(‘r’)+1;

          if(!useString.startWith(“C:r”))

                   thrownew TypeConversionException(“Invalid Syntax”);

          intradius;

          try

          {

                   radius=Integer.parseInt(userString.substring(radiusIndex));

          }

          catch(NumberFormatExceptione)

          {

                   thrownew TypeConversionException(“Invalid Value for Radius”);

          }

 

          circle= new Circle();

          circle.setRadius(radius);

          returncircle;

}

}

 

 

配置框架使用自定义转换器

1.     属性专用

属性文件ActionName-conversion.properties与动作类在同一个包中。

circle=com.aowin.utils.CircleTypeConverter

其中circle是动作类中的属性名,Circle类。

 

2.     全局类型转换

指定所有相应类型都使用自定义的转换器。

属性文件:xwork-conversion.properties文件,并放在src目录中。

文件内容:

com.aowin.model.Circle=com.aowin.utils.CircleTypeConverter.

类名=对应类型转换器

 


 

文件上传

默认拦截器栈包含了拦截器:FileUploadInterceptor

<interceptorname=”fileUpload”

                  class=”org.apache.struts2.interceptor.FileUploadInterceptor”/>

 

由fileUpload拦截器添加的请求参数,在动作类中追加与表中名字匹配的JavaBean属性。

参数名字

参数类型和值

myFile(来源于表单文件上传域的name属性值)

File——被上传的文件

myFileContentType

String——文件的内容类型

myFileFileName

String——存储在服务器上的上传文件名

 

 

文件上传表单的jsp代码片段:

<s:form action=”ImageUpload”method=”post” enctype=”multipart/form-data”>

         <!—enctype属性告诉框架这个请求被当作上传处理,否则无法工作-->

        

<!—name 属性提供的值用来构建接收上传数据的JavaBean属性-->

<s:filename=”pic” label=”Picture”/>

         <s:submit/>

</s:form>

 

 

文件上传处理的动作(xml文件)

<package name=”secure” namespace=”/secure”extends=”struts-default”>

         … …

         <actionname=”ImageUpload” class=”com.awoin.action.ImageUpload”>

                  <!—Param元素的name属性值对应与相应的动作类中的javaBean属性,元素文本内容会传递给此属性在此是设置文件保存路径,./表示了eclipse安装根目录-->

                  <param name="fileSystemPath">./portfolioFS</param>

                  <result>/ImageAdded.jsp</result>

                  <resultname=”input”>/ImageUploadForm.jsp</result>

         </action>

         … …

</package>

 

对应的动作类

public class ImageUpload extends ActionSupport

{

            //不需要实现所有的参数javaBean属性。

   private Filepic;

   private StringpicContentType;

   private StringpicFileName;

   private String fileSystemPath;

 

   private PortfolioService portfolioService;

  

   public String execute()

   {

      try

      {

          PortfolioService.addImage(getPic(),getPicFileName(),                                    getFileSystemPath());

      }catch(IOExceptione)

      {

          e.printStackTrace();

      }

     

      return SUCCESS;

   }

  

   … …

}

 

框架支持相同参数名上传多个文件,只需把动作类的javaBean属性改为数组。

 

与Servlet相关的各种接口

动作可以实现任意数量的接口,每个接口包含一个方法——当前资源的设置方法

l  ServletContextAware 设置ServletContext

l  ServletRequestAware 设置HttpServletRequest

l  ServletResponseAware 设置HttpServletResonse

l  ParameterAware 设置Map类型的请求参数

l  RequestAware 设置Map类型的请求属性

l  SessionAware 设置Map类型的会话属性

l  ApplicationAware 设置Map类型的应用程序领域属性

l  PrincipalAware 设置Principal对象(安全相关)

 

通过exception拦截器建立异常处理

xml文件中的代码片段:

<global-results>

       <!—全局结果,对包内所有动作可见-->

       <resultname=”error”>/error.jsp</result>

<global-results>

 

<global-exception-mappings>

       <!—告诉exception拦截器一个给定异常呈现哪个结果-->

       <exception-mappingexception=”java.lang.Exception” result=”error”/>

</global-exception-mappings>

 

exception拦截器会创建一个ExceptionHolder对象,放在ValueStack最顶端,它把跟踪栈和异常作为javaBean属性公开处理,可以在错误页面访问这些属性。

<p><Exception Name:<s:property value=”exception”/></p>

<p>What you did wrong:<s:property value=”exceptionStack”/></p>


 

声明拦截器

每一个package元素只能包含一个interceptors元素,并且这个元素必须出现在xml文档中一个特定位置。

<!ELEMENT struts (package|include|bean|constant)*>

<!ELEMENTpackage (result-types?, interceptors?,default-interceptor-ref?,

       default-action-ref?,global-results?,global-exception-mappings?,action*)>

 

将一系列拦截器和特定动作关联起来

<actionname=”MyAction” class=”com.aowin.myactions.MyAction”>

       <interceptor-ref name=”timer”/>

       <interceptor-ref name=”logger”/>

       <!--只要声明了自己的拦截器默认值失效,默认拦截器必须显式指出-->

       <interceptor-ref name=”defaultStack”/>

       <result>Success.jsp</result>

</action>

 

 

设置、覆盖拦截器参数

interceptor-ref是传入参数的地方

<interceptor-refname=”workflow”>

       <param name=”excludeMethods”>inputback,cancel,browse</param>

</interceptor-ref>

 

若想重用包含这个引用的defaultStack,并想改变exclude-Methods参数值

如下所示:

<action name=”MyAction”class=”com.aowin.myactions.MyAction”>

       <interceptor-ref name=”defaultStack”>

              <paramname=”workflow.excludeMethods”>doSomething</param>

       </interceptor-ref>

       <result>Success.jsp</result>

</action>

 


 

构建自定义拦截器(身份验证)

注意:拦截器实例在动作之间共享,每一个请求都会创建动作的一个新实例,但是拦截器会重用。拦截器是无状态的,不要在拦截器中存储与当前正在处理的请求相关的数据。

1.   实现Interceptor接口

编写一个拦截器,需实现com.opensymphony.xwork2.interceptor.Interceptor接口。

public interfaceInterceptor extends Serializable

{

        void destroy();

        void init();

       Stringintercept(ActionInvocation invocation) throws Exception;

}

 

2.   构建AuthenticationInterceptor拦截器

当AuthenticationInterceptor触发时,它检查用户对象是否出现在会话中。若出现在会话中,它就让动作像往常一样触发。否则重定向到登录页面,终止工作流。

 

 

首先查看login动作类,验证用户身份并将其存储在会话作用域中

//实现SessionAware接口用来存储会话域对象

public classLogin extends ActionSupport implementsSessionAware

{

        private User user;

        private Map session;

        private UserService userService;

 

        public String execute()

        {

               //验证用户在数据库中是否存在

               User logUser=userService.authenticateUser(user.getUsername(),

                                                         user.getPassword());

               if(logUser == null)

               {

                      return INPUT;

               }

               else

               {

                      session.put(“user”,logUser);

               }

               retrun SUCCESS;

        }

 

… …//省略其他gettersetter方法

}

 

 

AuthenticationInterceptor拦截器的代码

public classAuthenticationInterceptor implements Interceptor

{

      public void destroy(){}

     

      public void init(){}

     

      public String intercept(ActionInvocationactionInvocation)throws Exception

      {

             //取得会话映射

             Mapsession=actionInvocation.getInvocationContext().getSession();

             Useruser=(User)session.get(“user”);

            

             if(user == null)

             {

                    //指向登录页面,此登录结果定义为了全局结果

                    return Action.LOGIN;

             }

             else

             {

                    Actionaction=(Action)actionInvocation.getAction();

                    //我们自定义的UserAware接口允许动作让用户对象

                          //自动注入到设置方法

                    if(action instanceofUserAware)

                    {

                           (UserAware)action).setUser(user);

                    }

                      //验证完成后调用ActionInvocation对象的invoke()方法,

                          //将控制权交给剩余的拦截器以及动作

                    returnactionInvocation.invoke();

             }

      }

}

3.xml文件中声明自定义的拦截器并构建新的默认栈

<packagename=”xxx” namespace=”/xxx/secure” extends=”struts-default”>

       <interceptors>

             

              <interceptor name=”authenticationInterceptor”

                     class=”com.aowin.utils.AuthenticationInterceptor”/>

 

              <interceptor-stackname=”secureStack”>

                     <interceptor-refname=”authenticationInterceptor”/>

                     <interceptor-refname=”defaultStack”/>

              </interceptor-stack>

 

       </interceptors>

 

       <default-interceptor-refname=”secureStack”/>

 

       . . . . . .

</package>

 

 


 

struts2视图标签

数据存储的场所:ActionContext

使用OGNL表达式将表单字段名绑定到对象中的具体属性,动作对象被放在ValueStack对象上,并且OGNL表达式指向这个栈上的属性。OGNL表达式可以根据任何一系列对象求值,ValueStack只是这些对象中的一个,默认的。这些对象全部存储在ActionContext中。

ActionnContext包含框架请求处理过程可以访问的所有数据,包含内容从应用程序数据到会话作用域或者应用程序作用域的映射。所有特定应用程序的数据,都存储在ValueStack它是ActionContext的一个对象

所有OGNL表达式都必须根据ActionContext包含的某一对象求值默认情况会选择ValueStack

 

OGNL表达式指向特定对象上的属性,每一个OGNL表达式解析都需要一个根对象(rootobject)。例如:

user.account.balance

指向user对象的account对象的balance属性,user对象会默认在ValueStack中查找。

 

ActionContext:

ValueStack

parameters

application

request

attr

session

 

 

 

 

 

 

 

 

 


名字

描述

parmeters

当前请求中请求参数的映射

request

请求作用域的属性的映射

session

会话作用域的属性的映射

application

应用程序作用域的映射

attr

按照页面、请求、会话、应用程序作用域的顺序,返回第一个出现的属性

ValueStack

包含当前请求的应用程序特定领域的所有数据

 

OGNL选择一个根对象解析的表达式:使用#操作符。例

#session[‘user’]   #application[‘count’]  #request[‘user’]

                  

ognl表达式动态创建Ma
p

 

 

过滤和投影集合

过滤:允许根据某种规则过滤一系列对象。接收一个包含N个对象的Collection,生成一个包含这些元素的子集的新集合。

投影:根据某个规则转换一系列对象。产生一个与原来输入集合元素数目相等的Collection,投影产生一对一的结果集合。

 

过滤的语法:collectionName.{?expression}

可以使用#this操作符来引用集合中正在被评估的元素。

投影的语法:collectionName.{expression}

实例代码:

OGNL表达式

描述

users.(?#this.age>30)

过滤,返回一个30岁以上用户的新集合

users.{username}

投影,返回一个用户名字符串的新集合

users.{firstName+’ ’+lastName}

投影,返回每一个用户全名字符串的新集合

users.{?#this.age>30}.{username}

先过滤再投影,返回年龄在30岁以上的用户名字符串的新集合

 


 

表达式语言的高级特性

1.    字面值和操作符

OGNL表达式语言的字面值

 

字面值类型

 

示例

 

 

Char

 

‘a’

 

 

String

 

‘hello’  “hello”

 

 

Boolean

 

true false

 

 

int

 

123

 

 

double

 

123.5

 

 

BigDecimal

 

123b

 

 

BigInteger

 

123h

 

 

OGNL表达式语言的操作符

 

操作符

 

示例

 

 

add(+)

 

2+4  ‘hello’+’world’

 

 

subtract(-)

 

5-3

 

 

multiply(*)

 

8*2

 

 

divide(/)

 

9/3

 

 

modulus(%)

 

9%3

 

 

increment(++)

 

++foo,foo++

 

 

decrement(--)

 

bar--,--bar

 

 

equality(==)

 

foo==bar

 

 

less than(<)

 

1<2

 

 

greater than(>)

 

2>1

 

 

OGNL表达式支持逗号表达式,每一个子表达式执行完毕后将控制权转交给下一个子表达式,最后返回最后一个子表达式的值,就是整个表达式的返回值。

逗号表达式:user.age=10,user.name=”chad”,user.username


 

 

2.    调用方法

从OGNL表达式语言调用方法

 

Java代码

 

OGNL表达式

 

 

utilityBean.makeRandomNumber()

 

makeRandomNumber

 

 

utilityBean.getRandomNumberSeed()

 

getRandomNumberSeed()

或者RandomNumberSeed

 

 

3.    访问静态方法和字段

有两种访问方式:

1.指定完全限定的类名。

语法:@fullClassName@property 或 methodCall

实例:@com.aowin.utils.Struts2Constants@USER

          @com.aowin.utils.myBean@startImageWrapper()

2.根据ValueStack解析。类似第一种,使用vs记号代替全类名,vs表示ValueStack

         @vs@USER

         @vs@startImageWrapper()

Struts2标签API语法

struts2标签可以分为:数据标签(datatag)、流程控制标签(control-flow tag)、UI标签(UI tag)和其他标签(miscellaneous tag)。

 

1.jsp语法

声明标签:

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

简单语法举例:

         <s:property value=”name”/>

2.Velocity语法

Struts2标签API使用Velocity宏实现。

#sform(“action=Register”)

 #stextfield(“label=Username” “name=username”)

 #spassword(“label=Password” “name=password”)

 #stextfield(“label=Enter a name” “name=protfolioName”)


#ssubmit(“value=Submit”)

#end

3.   FreeMarker语法

<@s.property value=”name”/>

 

OGNL设置标签属性

若一个属性类型是String,,写入的属性值会被作为字符串字面值解析。

若一个属性不是String类型,写入的值被作为OGNL表达式解析。例:

<s:propertyvalue=”theProperty”/>

<s:propertyvalue=”theProperty” default=”doesNotExist”/>

注:value属性为Object类型,会从ValueStack上取得同名属性值,并写到页面上。

         由于未使用#操作符来指定ActionContext中的对象,会默认在ValueStack上查找。

         若不存在,则一个空值会被转为空串。第二个标签指定了default属性,在value指定的属性不存在的情况下,会显示此default的值,是string类型,直接显示字面值。使%{expression}可强制将字符串当作OGNL表达式解析


 

数据标签

1.     property标签

property标签的属性

属性

是否必须

默认值

类型

描述

value

栈最顶端

Object

被显示的值

default

空(null)

String

值为空时使用的默认值

escape

true

Boolean

是否转义HTML

 

例:<s:property value=”user.username”/>

1,访问Action值栈中的普通属性:

<s:propertyvalue="attrName"/>

2,访问Action值栈中的对象属性(要有get set方法):

<s:propertyvalue="obj.attrName"/>

<s:propertyvalue="obj1.obj2.attrName"/>

3,访问值栈中对象属性的方法

<s:propertyvalue="obj.methodName()"/>

4,访问值栈中action的普通方法:

<s:propertyvalue="methodName()"/>

5,访问静态方法:

<s:propertyvalue="@com.softeem.LoginAction@methodName()"/>

6,访问静态属性:

配置属性文件,允许ognl访问静态方法struts.ognl.allow...=true

<s:propertyvalue="@com.softeem.LoginAction@attrName"/>

7,访问Math类的静态方法:

<s:propertyvalue="@@min(9,7)"/>

8,访问普通类的构造方法:

<s:propertyvalue="new com.softeem.User(2)"/>

9,访问集合:

①list集合对象

<s:propertyvalue="listName"/>

②list集合中的某个元素

<s:propertyvalue="listName[1]"/>

③list中某个属性的集合

<s:propertyvalue="listName.{field}"/>

④list中某个属性集合的特定值

<s:propertyvalue="listName.{field}[0]"/>

⑤访问set

<s:propertyvalue="setName"/>

⑥访问set中某个元素

<s:propertyvalue="setName[0]"/>

⑦访问map

<s:propertyvalue="mapName"/>

⑧根据key访问Map中的元素

<s:propertyvalue="mapName.username"/>

<s:propertyvalue="mapName['username']"/>

<s:propertyvalue="mapName[/"username/"]"/>

⑨访问map中所有的key

<s:propertyvalue="mapName.keys"/>

10,访问map中所有的values

<s:propertyvalue="mapName.values"/>

11,访问map的大小

<s:propertyvalue="mapName.size()"/>

12,投影

<s:propertyvalue="listName.{?#this.age==1}"/>

<s:propertyvalue="listName.{^#this.age>1}"/>

<s:propertyvalue="listName.{$#this.age==1}"/>

<s:propertyvalue="listName.{$#this.age==1}.{age}==null"/>

[]:<s:propertyvalue="[0]"/>值栈中的对象

 

2.     set标签

set标签的属性

属性

是否必须

类型

描述

name

String

被设置在指定作用域内的变量的引用名

scope

String

Application、session、request、page或者action

默认值为action(ActionContext)

value

Object

设置值的表达式

 

例:

<s:setname=”username” value=”user.username”/>

hello,<s:propertyvalue=”#username”/>.How are you?

注解:set把user.username表达式的值设置到标签name属性指定的引用上,由于为指定作用域。默认放在了ActionContext中,直接用#来进行引用

 

设置在application作用域中

<s:setname=”username” scope=”application” value=”user.username”/>

hello,<s:propertyvalue=”#application[‘username’]”/>.How are you?

 

3.     push标签

把属性放到ValueStack的顶端,这样可以直接引用此属性所包含的对象

push标签的属性

属性

是否必须

类型

描述

value

 Object

放到ValueStack中的值

例:

<s:push value=”user”>

         <s:propertyvalue=”portfolioName”/>

         <s:propertyvalue=”username”/>

</s:push>

结束标签会将user从ValueStack顶端删除。

4.     bean标签

bean标签像是set标签和push标签的混合标签。可以自己创建一个对象的实例,并放到ValueStack上或者设置为ActionContext的顶级引用,默认放到ValueStack上,并且标签存在期间一直保留在ValueStack上。若想在标签之外继续引用创建的对象,可以使用var属性指定一个引用名,此引用会作为一个命名参数存在于ActionContext中,在请求周期内可以使用#操作符访问这个对象。

bean标签的属性

属性

是否必须

类型

描述

name

String

被创建bean的包名和类名

var

String

在结束标签作用域之外引用这个bean时使用的变量名

事例展示:

<s:beanname=”org.apache.struts2.util.Counter” var=”counter”>

         <s:param name=”last” value=”7”/>

</s:bean>

 

<s:iteratorvalue=”#counter”>

         <li><s:property/></li>

</s:iterator>

bean在ActionContext中,要用#操作符来命名它,若不使用var属性,则bean放在ValueStack上。

<s:property/>没有指定任何属性,只输出ValueStack最顶层的属性。

 

另一个事例:将bean放在ValueStack上

<s:beanname=”com.aowin.utils.JokeBean”>

         <s:paramname=”jokeType”>knockknock</s:param>

         <s:property value=”statrAJoke()”/>

</s:bean>

对象放在了ValueStack中,使用OGNL方法调用了对象的方法startAJoke();

 

 

5.     action标签

这个标签允许我们从当前视图层调用其他的动作。

action标签的属性

属性

是否必须

类型

描述

name

String

动作名

namespace

String

动作的命名空间,默认使用当前页面的命名空间

var

String

在页面后续代码中使用的动作对象的引用名

executeresult

Boolean

设置为true时执行动作的结果(默认为false)

flush

Boolean

设置为true时在action标签结尾会刷新写出缓冲(默认为true)

ignoreContextParams

Boolean  

设置为true时动作被调用时不包括请求参数(默认为false)

 

<s:action name=”TargetAction”executeResult=”true”/>辅助动作的结果视图应该是一个html片段。

 

主动作页面可以访问辅助动作的数据。

<s:action name=”TatgetAction”/>

<s:propertyvalue=”#request.dataFromSecondAction”/>访问辅助动作action中放到请求中的数据。

控制标签

1.   iterator标签

遍历集合对象。

action标签的属性

属性

是否必须

类型

描述

value

Object

被遍历的对象

status

String

若指定,这个属性指定的名字会引用IteratorStatus对象,并放在ActionContext中,主要用于计数

 

实例如下:

<s:iteratorvalue=”users” status=”itStatus”>

         <li>

                  <s:property value=”#itStatus.count”/>

                  <s:propertyvalue=”portfolioName”/>

         </li>

</s:iterator>

在标签内部每个对象轮流放在ValueStack顶端。itStatus引用IteratorStatus对象,然后进行遍历状态。

 

IteratorStatus对象的公有方法:

方法名

返回值

getCount

int

getIndex

int

isEven

boolean

isFirst

boolean

isLast

boolean

isOdd

boolean

modulus(int operand)

int

 

2.   if和else标签

if和elseif标签属性

属性

是否必须

类型

描述

test

Boolean

对被求值进行测试的布尔表达式

 

实例如下:

<s:iftest=”user.age > 35”>This user is too old.</s:if>

<s:elseiftest=”user.age<20”>This user is too young</s:elseif>

<s:else>Thisuser is just right</s:else>

 


 

其他标签

1.   include标签

在当前呈现页面中包含其他Web资源的输出。可以向被包含的资源传递请求参数

include标签可以引用任何的Servlet资源,而action标签只能包含动作。

include标签属性

属性

是否必须

类型

描述

value

String

页面、动作、Servlet及其他可以被引用的url名字

 

 

2.   URL标签

URL标签属性

属性

是否必须

类型

描述

value

String

基础URL,默认为呈现当前页面的URL

action

String

生成的URL执行的动作名,不需要.action扩展名

var

String

若指定,url不会被写出,会存在ActionContext中留待后用

includeParams

String

从all、get、none中选择参数,默认值为get

includeContext

Boolean

若为true,则生成的URL会使用程序的Context作为前缀,默认值为true

encode

Boolean

若不支持Cookie,会将Session ID追加在生成的URL中

scheme

String

指定协议,默认使用当前协议(HTTP/HTTPS)

 

举例:

<s:url action=”IteratorTag”var=”myUrl”>

       <s:param name=”id” value=”2”/>

</s:url>

<a href=’<s:propertyvalue=”#myUrl”/>’>Click Me</a>

生成如下url标记:<a href=’/应用程序名/namespace/IteratorTag.action?id=2’>

 

<a href=’<s:urlvalue=”IteratorTag.action”/>’>Click Me</a>


 

3.   i18n和text标签

用于国际化支持的标签。

text标签用来显示与具体语言相关的文本,这个标签使用一个关键字在一系列文本资源中查找,这个标签从属性文件ResourseBundle中取得消息值。框架默认的Locale判断机制判断在哪个Locale对应的文本资源中解析这个关键字。

text标签属性

属性

是否必须

类型

描述

name

String

在ResourceBundle中查找用的关键字

var

String

若找到,文本会使用这个名字保存在ActionContext

 

可以命名一个特别的ResourceBundle来解析text标签,若手动指定ResourceBundle,可以使用i18n标签

i8n标签属性

属性

是否必须

类型

描述

name

String

            ResourceBundle的名字

 

举例如下:

<s:i18n name=”com.aowin.myResourceBundle_tr”>

         In<s:text name=”language”/>

         <s:textname=”girl” var=”foreignWord”/>

</s:i18n>

 

<s:property value=”#foreignWord”/>means girl.

 

 

4.   param标签

param标签属性

属性

是否必须

类型

描述

name

String

参数名

value

Object

参数值

 


 

UI组件标签(表单)

所有UI标签的通用属性

属性

主题

数据类型

描述

name

simple

String

设置表单输入元素的name属性,name属性指向ValueStack上的属性作为提交的请求参数值的目标

value

simple

Object

指向ValueStack上的属性的OGNL表达式,用来为预填充设置表单输入元素的值。默认为name属性设定的值

key

simple

String

从ResourceBundle取得本地化的标签(label),可以传播到name属性,也可传播到value属性

label

XHTML

String

为组件创建一个HTML标签(label),若设定使用key属性和本地化的文本就不需要指定这个属性

labelPosition

XHTML

String

元素标签(label)的位置,可选的值是left或者top

required

XHTML

Boolean

若为true,则标签(label)旁边会出现一个星号来暗示这是必需字段。默认情况下,若一个字段级别的数据验证器通过name属性与这个输入字段关联时,这个值为true

id

simple

String

HTML的id属性,若id属性未指定,则组件会创建一个唯一标识(由动作名和表单name属性值组成,‘_’分隔)

cssClass

simple

String

HTML的class属性,css使用

cssStyle

simple

String

HTML的style属性,CSS使用

disabled

simple

String

HTML的disabled属性

tabindex

simple

String

HTML的tabindex属性

theme

N/A

String

在哪个主题下呈现这个组件,例xhtml、css_xhtml、ajax或simple。默认值是xhtml,在default.properties中设置

templateDir

N/A

String

用来覆盖从中取出模板的默认目录名

template

N/A

String

用来呈现UI标签的模板,所有的UI标签都有默认的模板(除了component标签),但是模板可以被覆盖

 

head标签

必须放在HTML的head元素内部,head标签会生成信息。这些信息包括css样式表和脚本元素。若某个标签依赖head标签引入的资源,则不可省去head标签。

例:

 

<head>

       <title>the title</title>

       <s:head/>

</head>

 

以下是标签创建的内容

<link rel=”stylesheet”href=”…styles.css” type=”text/css”/>

<script type=”text/javascript”src=”…dojo.js”/>

<scripttype=”text/javascript” src=”dojoRequire.js”/>

 

form标签

常用的form标签属性

属性

数据类型

描述

action

String

表单提交的动作目标,可以是动作名字(无.action扩展名)或URL

namespace

String

Struts2命名空间,在这个命名空间中查找命名动作(action属性)或者从这里开始构建URL,默认为当前命名空间

method

String

与HTML form属性相同,默认是POST

target

String

与HTML form属性相同,请求的资源打开的位置

enctype

String

上传文件时设置为multipart/form-data

validate

Boolean

与验证框架一起使用,打开客户端JavaScript验证

 

 

(1)若没有指定action属性,则重新执行生成当前页面的动作。

(2)action中指定的值不是声明性架构中的Struts2动作,则此值会被用来直接构建URL。若指定的字符串以一个斜线(/)开头,则被假定为与ServletContext相关,框架会在它之前加上ServletContext的路径构建一个URL,若没有已斜线开头,则此值被直接当作URL(如http://www.baidu.com)。若指定的既不是动作,也不是以斜线开头,也不是完整的URL,则会将当前表单的视图路径去掉最后的文件/动作名然后与action的值进行拼接构造一个请求URL。举例:

<s:form action=”MyResource”>

若此表单的地址是:http://localhost/theApp/my/LoginForm.action

则构造的请求地址是:http://localhost/theApp/my/MyResource

 

 

textfield标签

重要的textfield标签属性

属性

数据类型

    描述

maxlength

String

字段数据的最大长度

readonly

Boolean

若为true,字段不可编辑

size

String

textfield的可视长度

 

 

 

 

示例如下:

<s:formaction=”Login”>

       <!—key属性会从ResourceBundle中取得本地化的标签,并且传播到name属性值为username.属性文件在类路径下为global-messages.properties -->

       <s:textfield key=”username”/>

       <s:password name=”password” label=”Password” />

       <s:submit/>

</s:form>

 

global-messages.properties内容如下:

username=Username

 

为了使用全局属性文件我们必须创建struts.properties文件并指定以下属性:

struts.custom.i18n.resources=global-messages

 

 

password标签

重要的password标签属性

属性

数据类型

    描述

maxlength

String

字段数据的最大长度

readonly

Boolean

若为true,字段不可编辑

size

String

文本字段的可视长度

showPassword

Boolean

若为true,且ValueStack中对应属性有值,则密码会被预填充。默认为false.

 

textarea标签

重要的textarea标签属性

属性

数据类型

    描述

cols

Integer

列数

rows

Integer

行数

readonly

Boolean

若无true,字段不可编辑

wrap

String

指定textarea中的内容是否应该被包装起来

 

 

 

 

checkbox标签

与此标签绑定的Java端的属性必须是Boolean类型的。对于一系列的多个相同名字的复选框可以使用checkboxlist标签。checkbox只关注true或者false选择。

重要的checkbox标签属性

属性

数据类型

    描述

fieldValue

String

被checkbox提交的真实值。可能是true或者false,默认为true

value

String

与fieldValue一起使用,决定checkbox是否被选中,若fieldValue=true,且value=true,则组件被选中

 

<s:checkbox name=”receiveMail”fieldValue=”true” label=”check to receive mail”/>

 

相应的HTML checkbox元素

<label for=”Register_receiveMail”>checkto receive mail</label>

<input type=”checkbox” name=”receiveMail”value=”true” id=”Register_receiveMail”/>

 

select标签——基于集合的组件

select(下拉列表)标签。用于构建下拉列表,允许用户从一系列选项中选择一个值。

简单事例:

<s:select name=”user.name”list=”{‘MIKE’,’Payal’,’Silas’}”/>

list 属性指向了为这个组件提供数据的数据集。通常情况会使用一个OGNL表达式指向ValueStack上的一系列的数据。

呈现的HTML标记

<select name=”user.name” id=”xx_user_name”><!—xx表示表单的action属性值-->

         <optionvalue=”Mike”>Mike</option>

         <optionvalue=”Payal”>Payal</option>

         <optionvalue=”Silas”>Silas</option>

</select>

 

重要的select标签属性

属  性

 数据类型

               描    述 

list

Collection、Map、Array或者Iterator

用来生成下拉列表选项的数据集合

listKey

String

当list中的元素是复杂类型时,用来指定用作被提交的值的list元素的属性,默认值是key

listValue

String

当列表中的元素是复杂类型时,用来指定用作选项内容的list元素属性,用户所看到的字符串,默认值是value

headerKey

String

与标题一起使用,若用户选择了标题,则指定提交的值

headerValue

String

作为list的标题呈现给用户,例如”States”、“Countries”

emptyOption

Boolean

与标题一起使用,在标题和真实选项之间放置一个空的间隔选项

multiple

Boolean

用户可以选择多个值

size

String

一次显示的选项个数

 

示例如下:

list属性指向java端的Collection对象

<s:form action=”xx”>

         <s:selectname=”username” list=”users” listKey=”username”

                                            listValue=”username”label=”Seclect an artist”/>

         <s:submitvalue=”Browse”/>

</s:form>

 

list属性指向java端的Map对象其中userskeyusername,valueUser对象

<s:form action=”xx”>

         <!--listKey默认被设置为key,会指向username,在此可以省略

                  listValue属性默认被设置为value,指向User对象,在这里指向User对象的

                  username属性更合适,即value.username-->

         <s:selectname=”username” list=”users” listKey=”key”

                                            listValue=”value.username”label=”Seclect an artist”/>

         <s:submitvalue=”Browse”/>

</s:form>

 

上述两种情况生成的html标记完全一样。

 

 

radio标签——基于集合的组件

单选组件。使用类似于select标签

重要的radio标签属性

属  性

 数据类型

               描    述 

list

Collection、Map、Array或者Iterator

用来生成单选项的数据集合

listKey

String

list中集合元素的属性,指定用作被提交的值,默认值是key

listValue

String

list中集合元素的属性,指定用作选项内容,用户所看到的字符串,默认值是value

 

checkboxlist标签——基于集合的组件

复选框列表组件,类似于select组件。

重要的checkboxlist标签属性

属  性

 数据类型

               描    述 

list

Collection、Map、Array或者Iterator

用来生成单选项的数据集合

listKey

String

list中集合元素的属性,指定用作被提交的值,默认值是key

listValue

String

list中集合元素的属性,指定用作选项内容,用户所看到的字符串,默认值是value

 

 

label标签

会生成一个只读的一个类似textfield的视图组件

<s:labelname=”username” label=”Username”/>

生成的结果:Username:Chad

 

hidden标签

隐藏请求的参数,而不展示给用户

<s:hidden name=”username”/>

 

 

 

 

 

doubleselect标签

关联下拉列表:将两个下拉列表链接在一起,当从第一个下拉列表中选择一个值时,第二个下拉列表中的选项会根据第一个下拉列表中的内容而变化。例如将省名和城市名称链接起来。

首先,需要告诉组件哪些数据用来生成第一个下拉列表,这些设置与select标签方式类似,使用相同的属性,相同方式执行。其次,需要指定另外一个属性用来提供第二个下拉列表需要使用的一系列数据。这个属性能够引用多个数据列表,每个列表对应着第一个下拉列表的选项。

 

示例如下:

<s:formaction=”xx”>

         <s:doubleselect name=”username”list=”users” listKey=”username”

                          listValue=”username” doubleName=”portfolioName”doubleList=”portfolios”  

            doubleListKey=”value.name”  doubleListValue=”value.name”/>

                  <s:submit value=”View”/>

</s:form>

 

其中portfolios是User对象的一个map集合属性。

 

 

<s:token/>标签防止重复提交

首先需要在表单中添加<s:token/>标签

         <s:form>

                  <s:token/>

                  <s:textfieldkey=”coinToss”/>

                  <s:submit action=”flipCoin”/>

         </s:form>

 

使用令牌拦截器声明动作映射

<actionname=”xx” method=”xxx” class=”xxxx”>

         <interceptor-refname=”myTokenStack”/>

         <resultname=”success”>samplePage</result>

         <result name=”invalid.token”>duplicatePage</result>

</action>

当检测到一个重复请求时,这个拦截器会返回invalid.token.

 

拦截器栈:

<interceptor-stackname=”myTokenStack”>

         <interceptor-ref name=”token”/>

         <interceptor-refname=”defaultStack”/>

</interceptor-stack>

 

比token拦截器更智能的版本是tokenSession拦截器,提供了更复杂的检查逻辑。

 

类中的某些方法不想参与测试令牌:

<interceptor-refname=”tokenSession”>

         <param name=”includeMethods”>sava,proceed</param>

         或者<param name=”excludeMethods”>someMethods</param>

</interceptor-ref>

若包含和排除参数同时存在,则包含优于排除。

 

或者

<interceptor-refname=”myTokenStack”>

         <paramname=”tokenSession.includeMethods”>sava,proceed</param>

         或者<param name=”tokenSession.excludeMethods”>someMethods</param>

</interceptor-ref>

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值