精华内容
下载资源
问答
  • Struts2 教程

    2020-10-20 13:22:41
  • Struts2教程

    2017-06-30 13:54:00
    Struts2教程 一、初识Struts2  Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。许多框架...

     

    一、初识Struts2

      Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。许多框架在大家一开始学习的时候都觉得比较繁琐和多此一举,但大体都有相同的目的,那就是增强可扩展性。Struts2的核心其实就是通过改配置文件的方式将请求和视图(结果)分开。

    1.1 开发环境搭建

      首先下载Struts2,地址http://struts.apache.org/,我这里下载的版本是2.5.10.1,解压之后有如下4个文件夹

      

      所需的基本jar包有以下9个。struts2-core是开发的核心类库,struts2UI标签的模板使用freemarker编写,OGNL是对象图导航语言,通过它来读写对象属性。

      

    1.2 Struts2配置文件

      ①web.xml文件

      主要完成对StrutsPrepareAndExecuteFilter的配置,它的实质是一个过滤器,负责初始化整个Struts框架并且处理所有的请求。在2.5以及2.1.3之前的版本filter-class会不同,请自行查询官方文档,filter-name和url-pattern是默认写法,不建议修改。

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
         <url-pattern>/*</url-pattern>
    </filter-mapping>
      ②struts.xml文件

      Struts2的核心配置文件就是struts.xml文件,在这个配置文件里面我们可以根据需要再包括其它一些配置文件。在通常的应用开发中,我们每个人来写不同的模块,每个人单独配置一个struts.xml文件,最后合并,这样也利于管理和维护。

      struts.xml中包含全局属性、用户请求和相应Action之间的对应关系、Action可能用到的参数和返回结果以及各种拦截器的配置,具体将在以下几节中慢慢介绍。

      struts.xml可以从解压过后的示例程序里复制,拷贝到工程的src目录下,注释或删除掉struts标签中的内容,来填写我们需要的配置。

      ③struts.properties(default.properties)

      default.properties文件在struts2-core.jar中的org.apache.struts2包下,里面保存着许多Struts是的默认属性,如编码格式、是否启用开发模式等等。当要修改某些属性时,建议在struts2的xml配置文档中进行更改,格式如下面一行代码,而不建议自己新建一个struts.properties文件。

    <constant name="" value=""></constant>
      ④struts-default.xml

      此文件是struts2框架默认加载的配置文件,它定义了struts2一些核心bean和拦截器,它会自动包含到struts.xml文件中(实质是通过<package  extends="struts-default">),并为我们提供了一些标准的配置。我们可以在struts2-core.jar中找到这个文件。

    二、struts.xml配置

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
            "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
            "http://struts.apache.org/dtds/struts-2.5.dtd">
    <struts>
         <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
        <package name="user" namespace="/user" extends="struts-default">
            <action name="user" class="com.dhcc.struts2.action.UserAction">
                <result>/user_add_success.jsp</result>
            </action>
        </package> 
    </struts>
    例子

    2.1 配置文件的优先级

      在struts2中一些配置(比如常量)可以同时在struts-default.xml(只读性),strtus-plguin.xml(只读性),struts.xml,struts.properties和web.xml文件中配置,它们的优先级逐步升高,即是说后面的配置会覆盖掉前面相同的配置。

      以struts.i18n.encoding=UTF-8的配置为例进行说明:

      在struts.xml配置形式如下:

    <constant name="struts.i18n.encoding" value="gbk"></constant>

      在struts.properties的配置形式如下:struts.i18n.encoding=UTF-8

      在web.xml中配置如下:

    <filter>
        <filter-name>struts2</filter-name>    
        <filter-class>
        org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
        </filter-class>
        <init-param>
            <param-name>struts.i18n.encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>

    2.2 package配置

    属性名

    是否必须

    说明

    Name

    Package的唯一标识,不允许同名

    Extends

    指定要继承的包

    Namespace

    指定名称空间

    Abstract

    声明包为抽象否

      package元素的namespace属性及action的name属性,它们共同定义了action所映射到的实质文件。

      namespace默认值“”,即不配置namespace属性,如果action不能进行完整路径匹配,则会来此namespace下进行匹配。namespace也可以配置成namespace="/"。它代表配置为项目的根。总结action的名称探索顺序:完全对应、逐步追溯到上级目录查找、"/"下查找、默认namespace下查找。

       namespace引发的链接问题:当我们为action配置了namespace时,访问此action的形式总会是如下形式:.../webappname/xxx/yyy/ActionName.action,而当此action成功执行跳转到某个jsp页面时,如想在此jsp页面写链接,一定要写绝对路径,因为相对路径是相对.../webappname/xxx/yyy/,而如果以后我们修改了action的namespace时,相对路径又要变,所以链接不能写成相对路径。 可以在建立一个jsp文件时,加上如下内容:

    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>

      我们写绝对路径可以参此内容。还可以参<head>下的<base href="<%=basePath%>"> 来完成绝对路径的书写。

    三、Action

    3.1 新建一个Action

     第一步,新建一个Class,继承ActionSupport ,ActionSupport实现了execute()方法。

    package com.struts2.test;
    import com.opensymphony.xwork2.ActionSupport;
    public class UserAction extends ActionSupport {
        public String add() {
            return "success";
        }
        public String del() {
            return "success";
        }
        public String update() {
            return "success";
        }
        public String query() {
            return "success";
        }
    }

     第二步,配置此Action,在struts.xml中加入如下内容:

    <package name="user" extends="struts-default" namespace="/user">
        <action name="addUser" class="com.asm.UserAction" method="add">
          <result name="success">/user/addUser.jsp</result>
        </action>
        <action name="delUser" class="com.asm.UserAction" method="del">
          <result name="success">/user/delUser.jsp</result>
        </action>
        <action name="updateUser" class="com.asm.UserAction" method="update">
          <result name="success">/user/updateUser.jsp</result>
        </action>
        <action name="queryUser" class="com.asm.UserAction" method="query">
          <result name="success">/user/queryUser.jsp</result>
        </action>
    </package>

     上面的method方法的值来源于CRUDAction中方法的名字,这样当我们访问上面的每一个Action时,它实质是和method指定的方法关联上。如果没有为action指定class,默认就是ActionSupport类,如果没有为action指定method属性,则默认执行execute方法,如果没有指定result的name属性,默认值为success。

     第三步,编写相应的jsp页面,在此略去crud文件夹下的四个跳转jsp页面(addSuccess.jsp等),重点是crud.jsp页面。内容如下:

    <html>
    <%
        String path=request.getContextPath();
    %>
        <body>
            <a href="<%=path %>/user/addUser.action">添加数据</a><br>
            <a href="<%=path %>/user/delUser.action">删除数据</a><br>
            <a href="<%=path %>/user/queryUser.action">查询数据</a><br>
            <a href="<%=path %>/user/updateUser.action">修改数据</a><br>
        </body>
    </html>

      最后发布测试。

    3.2 动态调用DMI

      不使用method实现统一,我们在struts.xml中增加如下内容:

    <action name="op" class="com.struts2.test.UserAction">
        <result name="add">/user/addUser.jsp</result>
        <result name="del">/user/delUser.jsp</result>
        <result name="query">/user/queryUser.jsp</result>
        <result name="update">/user/updateUser.jsp</result>
    </action>

      然后再在crud.jsp中定义如下链接:

    <a href="<%=path %>/user/op!add.action">添加数据</a><br>
    <a href="<%=path %>/user/op!del.action">删除数据</a><br>
    <a href="<%=path %>/user/op!query.action">查询数据</a><br>
    <a href="<%=path %>/user/op!update.action">修改数据</a><br>

      注意查看上面的链接地址,它们都是针对op这个action,然后再加地上“!+UserAction中相应的方法名”,最后再写上.action即可以访问到相应result的name指定的jsp。大家会发现跟上面不同的是,result的name不再都是SUCCESS,这样才能区分开要访问的页面,但千万不要忘记在UserAction中相应的方法也要返回add/del/query/update,而不是SUCCESS。如果不想使用动态方法调用,我们可以通过常量来关闭,即在struts.xml中增加如下配置:

    <constant name="struts.enable.DynamicMethodInvocation" value="false"/>

    3.3 通配符

      为了使用通配符,只需要改写配置文件即可。将3.1节中的配置文件改为如下内容可达到相同的效果:

    <package name="user" extends="struts-default" namespace="/user">
        <action name="*User" class="com.asm.UserAction" method="{1}">
        <result name="success">/crud/{1}User.jsp</result>
    </package>

      当有.../addUser.action请求时,如果不能在当前应用中找到完全相同的addUser名字的Action时,通配符配置这时就起作用了。

       其实如果我们有良好的编程命名习惯,所有的Action我们都只需要进行一次配置。举例:规定所有的Action类都用XXXAction来命名,类中所有的CRUD方法都用add/del/update/query。Jsp页面也用add/del/update/query_XXX.jsp这样的形式。即配置文件可以写成如下形式:

    <action name="*_*" class="com.struts2.test.{2}Action" method="{1}">
        <result name="success">.../{1}_{2}.jsp</result>
    </action>

      name中第一个*代表CRUD操作的名字,第二个*代表类的名字。所以访问链接地址举例如:.../del_User.action将访问到UserAction类的del方法,成功后跳到del_User.jsp页面。说明{0}是代表name中所有的*组合。

     3.4 接收参数

      ①Action属性接收参数

      UserAction中建两个属性name和age,并且要生成相应的get/set方法。

    public class UserAction extends ActionSupport {   
        private String name;
        private int age;public int getAge() {
          return age;
        }
        public String getName() {
          return name;
        }
        public void setAge(int age) {
          this.age = age;
        }
        public void setName(String name) {
          this.name = name;
        }
    } 

      在传参的jsp页面,有一个表单

    <form action="<%=request.getContextPath()%>/addUser.action" method="get">
        名字:<input type="text" name="name"><br>
        年龄:<input type="text" name="age"><br>
        <input type="submit" value="login">
    </form>

      这样name和age就能接收到传入的值。需要注意的是,传参参照的action中的方法名,而非属性名。

      ②DomainModel接收参数

      UserAction中有一个域模型private User user,注意不要自己new对象,User类中有name和age属性和对应的get/set方法。UserAction中要生成User对象对应的get/set方法。

      访问http://.../user/user!add?user.name=a&user.age=8 即可对user赋值,相当于调用了user的set方法。

    public class UserAction extends ActionSupport {   
        private User user;public User getUser() {
            return user;
        }
        public void setUser(User user) {
          this.user = user;
        }  
    }    
    • 如果传入的参数个数和域模型的属性个数不同,可以用DTO(Data Transfer Object)。比如传入的参数还有一个isAdmin,那么我们建一个UserDTO,包含name,age和isAdmin三个属性,用UserDTO去接收参数,然后用UserDTO再生成相应的User

      ③ModelDriven接收参数

    public class UserAction extends ActionSupport implements ModelDriven<User>{   //需要实现ModelDriven接口
        private User user = new  User();  //ModelDriven需要自己new
        @Override
        public User getModel() {
            return user;
        }   
    }

    3.5 访问Scope对象(request、session、application,HttpServletRequest、HttpSession、ServletContext)

      ①与Servlet解耦合的非IOC方式

    public class LoginAction extends ActionSupport {
        ActionContext context;
        Map request;
        Map session;
        Map application;
        public String execute() throws Exception {
            context=ActionContext.getContext();
            request=(Map) context.get("request");
            session=context.getSession();
            application=context.getApplication();
            
            request.put("req", "requst属性");
            session.put("ses", "sesion属性");
            application.put("app", "application属性");
            return SUCCESS;
        }
    }
    主动获取

      ②与Servlet解耦合的IOC方式

    public class Login2Action extends ActionSupport implements RequestAware,SessionAware,ApplicationAware { //实现XxxAware接口,重写setXxx()方法
        Map request;
        Map session;
        Map application;
        public String execute() throws Exception {
            request.put("req", "requst属性");
            session.put("ses", "sesion属性");
            application.put("app", "application属性");
            return SUCCESS;
        }
        public void setRequest(Map<String, Object> request) {
            this.request=request;
        }
        public void setSession(Map<String, Object> session) {
            this.session=session;
        }
        public void setApplication(Map<String, Object> application) {
            this.application=application;
        }
    }
    依赖注入与控制反转

      ③与Servlet耦合的非IOC方式

    public class Login3Action extends ActionSupport { //获取的纯粹的Scope对象,它与容器相关
        HttpServletRequest request;
        HttpSession session;
        ServletContext application;
        public String execute() throws Exception {
            request = ServletActionContext.getRequest();
            session = request.getSession();
            application = ServletActionContext.getServletContext();
    
            request.setAttribute("req", "requst属性");
            session.setAttribute("ses", "sesion属性");
            application.setAttribute("app", "application属性");
            return SUCCESS;
        }
    }
    主动获取

      ④与Servlet耦合的IOC方式

    public class Login4Action extends ActionSupport implements ServletRequestAware,ServletContextAware{ //实现XxxAware接口,重写SetXxx()方法
        ActionContext context;
        HttpServletRequest request;
        HttpSession session;
        ServletContext application;
        public String execute() throws Exception {
            context=ActionContext.getContext();
            session=request.getSession();    
            request.setAttribute("req", "requst属性");
            session.setAttribute("ses", "sesion属性");
            application.setAttribute("app", "application属性");
            return SUCCESS;
        }
        
        public void setServletRequest(HttpServletRequest request) {
            System.out.println("测试:"+request);
            this.request=request;
        }
        public void setServletContext(ServletContext application) {
            System.out.println("测试:"+application);
            this.application=application;
        }
    }
    依赖注入与控制反转DI/IOC

      之后可以在jsp中使用EL表达式${requestScope.req}或通过request.getAttribute这样的方式获取对象值

    3.6 default-action-ref 配置统一访问

      当访问没有找到对应的action时,默认就会调用default-action-ref指定的action。在struts.xml文件的package中增加如下内容:

    <default-action-ref name="error"></default-action-ref>
        <action name="error">
            <result>/other/error.jsp</result>
        </action>

      上面一段内容就是说当我们访问的action不能被找到时便指向名为error的action中去,接着我们在下面配置了这个error Action。但是要注意,一个package内只配置一个<default-action-ref>,如果配置多个,就无法预测结果了。此时我们只要输入.../myStruts2/luanFangWen.action这样的形式,它就会去访问这个默认的<default-action-ref>,通常我们会为它配置一个错误页面,以提示用户访问的页面不存在。 在web开发中,我们还可以把这个默认的action访问配置成主页,这样当用户访问一些不存在的action时,总会跳到主页上去。

      通过此配置,只要是访问一个不存在的action便会转向到.../other目录下的error.jsp页面。但是如果访问是其它的不存在资源则仍是报tomcat所标识的404错误,我们可以在web.xml中作如下配置:

    <error-page>
        <error-code>404</error-code>
        <location>/other/404error.jsp</location>
    </error-page>

    四、Result配置

    4.1 type类型

      在前面的许多案例中我们所用到的Action基本都继承自ActionSupport这个类,而在这个类中我们定义了五个字段:SUCCESS,NONE,ERROR,INPUT,LOGING。我们可以直接返回这些字段值,这些字段值实质是被定义成:String SUCCESS=”success”这样的形式,所以我们只要在Result元素中用它们的小写即可。

    <result name="success" type="dispatcher">
        <param name="location">/default.jsp</param>
    </result>

      如果我们都采用默认的形式,最终可以简写成:<result>/default.jsp</result>

    Type类型值

    作用说明

    chain

    用来处理Action链

    dispatcher

    用来转向页面,通常处理JSP

    redirect

    重定向到一个URL

    redirectAction

    重定向到一个Action

    plainText

      显示源文件内容,如文件源码

    freemarker

    处理FreeMarker模板

    httpheader

    控制特殊http行为的结果类型

    stream

     

    向浏览器发送InputSream对象,通常用来处理文件下载,还可用于返回AJAX数据。

    velocity

    处理Velocity模板

    xslt   

      处理XML/XLST模板

    json

    序列化action为json

      当一个Action处理后要返回的Result是另一个Action,就需要使用chain和redirectAction。以chain为例,它的param有4个值可配,actionName(默认)、namespace、method和skipActions。namesapace的默认值当前namespace,可以省略不写。method用于指定转向到一个目标action所调用的方法,默认是调用下一个action的execute方法,所以也可以省略。SkipActions是一个可选的属性,一般不用。

    <package name="public" extends="struts-default">
        <!-- Chain creatAccount to login, using the default parameter -->
        <action name="createAccount" class="...">
            <result type="chain">login</result>
        </action>
     
        <action name="login" class="...">
            <!-- Chain to another namespace -->
            <result type="chain">
                <param name="actionName">dashboard</param>
                <param name="namespace">/secure</param>
            </result>
        </action>
    </package>
     
    <package name="secure" extends="struts-default" namespace="/secure">
        <action name="dashboard" class="...">
            <result>dashboard.jsp</result>
        </action>
    </package>
    example

      注意:如果result中指定type类型为redirect,要想传递参数可以在result指向的jsp页面中附加参数即可,我们可以在test2 action的result中写成:

    <result name="success" type="redirect">/test2Suc.jsp?username=${username}</result>

      随后在test2Suc.jsp页面中引用时会出现三个问题:

      1.EL表达式引用失效,(EL表达式应该使用${param.username}形式)。我们也可以使用<%=request.getParameter("username")%>获取参数值。

      2.由于在前面的TestAction中设定的值为中文,而附加到这里的uri请求的参数后面时会出现乱码问题。(可以使用URI编码再解码解决此问题)

      3.值栈取值失效:因为每一次request共享同一个值栈,所以服务器端的forward跳转也是能共享同一值栈得。但是当redirect重定向到test2Suc.jsp页面,这时其实就是重发的一次request,所以前一个action保存的值栈内容全部失效。这也就是为什么我们要附加参数的原因。

    4.2 global-results(全局result)

      如果我们所有的action均有可能跳到相同的页面,则不防使用全局result。为了方便引用我们专门建立一个package来存放公共的result。在会用到个全局的跳转时,只需要继承自这个公共的package即可。建立公共包,代码如下:

    <package name="pubResult" extends="struts-default" abstract="true">
        <global-results>
            <result name="error">/error.jsp</result>
        </global-results>
    </package> 

      由于它下面没的action配置,所以我们可以像默认的struts-default包一样,声明abstract=true,这样声明表示此packgage下不会有action,它一般是用来让别的package继承。随后再在要用到全局result中引用这个公共的package。代码如下:

    <package name="testGlobal" extends="pubResult" >
        <action name="error" class="com.struts2.ErrorAction"></action>
        <action name="error2" class="com.struts2.Error2Action"></action>
    </package>

      这样操作相当于把全局的result加到了此package下的所有action中去。

    4.3 动态result(了解)

      action中的变量r,设置了get/set方法,在struts.xml中使用${r}根据不同的值对应到不同的result。

    public class DynaAction extends ActionSupport {
        private String username;
        private String nextAction;
    
        public String execute() throws Exception {
            if (username.equals("admin")) {
                nextAction = "admin";
            } else if (username.equals("user")) {
                nextAction = "user";
            } else {
                nextAction = ERROR;
            }
            return SUCCESS;
        }
        ...省略get/set方法    
    }
    action示例
    <package name="dynaTest" extends="pubResult">
            <action name="dyna" class="com.asm.DynaAction">
                <result name="success" type="chain">${nextAction}</result>
            </action>
    
            <action name="admin" >
                <result>/admin.jsp</result>
            </action>
    
            <action name="user">
                <result>/user.jsp</result>
            </action>
    </package>
    struts.xml示例

      当把参数传递到DynaAction中去时,如果传递的值为admin,我们便设定了nextAction的值admin,在配置文件中我们通过${nextAction}(用在struts配置文件中的ognl,其实nextAction的值是存在值栈中,我们通过${}这样的形式取出,在此只作了解,后面的章节详细介绍)来获取值便为admin,随后再继续把请求传递到下一个Action中去(此时也即admin.action),为了方便我们设定了两个ForwardActionadmin.action和user.action。这样便可以跳到指定的jsp页面。 原理:dyna.action执行后会继续把请求传递给下一个Action,而下一个Action的到底是哪一个Action,是通过DynaAction中动态指定的,比如这里是根据传递的username的值指定。

    五、ValueStack(值栈)

      1.ValueStack是一个接口,在struts2中使用OGNL(Object-Graph Navigation Language)表达式实际上是使用实现了ValueStack接口的类OgnlValueStack.它是ValueStack的默认实现类.

      2.ValueStack贯穿整个action的生命周期,每一个action实例都拥有一个ValueStack对象,其中保存了当前action对象和其他相关对象.

      3.struts2把ValueStack对象保存在名为:struts.valueStack的request域中.即ValueStack作用域为request.当action创建的时候,ValueStack就创建了,action被销毁的时候,ValueStack就销毁了

      4.ValueStack中的数据分两部分存放:root(对象栈,也称Object Stack,CompoundRoot)和context(Map栈,OgnlContext),Struts将把动作和相关对象压入Object Stack,而把各种各样的映射关系压入Context Map。

    • 其中的root对象是CompoundRoot,CompoundRoot继承了ArrayList,提供了额外的方法:push(),和pop()方法,用来对root对象中所包含的数据进行存取。正是由于这两个方法,CompoundRoot变成了一个栈结构。struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以action对象是CompoundRoot中的一个元素。
    • 其中的context对象是OgnlContext,它实现了map接口,在valuestack的默认实现类中,即OgnlValueStack类中,调用ongl中的方法:Ognl.createDefaultContext(..)给context赋值,查看源代码可知,此方法返回的是一个OgnlContext对象。

      5.获取valueStack的三种方法:

     ValueStack v1 = ActionContext.getContext().getValueStack();
         ValueStack v2 = ServletActionContext.getValueStack(ServletActionContext.getRequest());
            ValueStack v3 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");

      6.ValueStack内存结构图

      

      在jsp中使用struts的<s:debug/>标签可以在页面上生成一个超链接,通过该链接可以查看ValueStack和Stack Context 中的所有值信息,如下图(Stack Context下面没有截全,大家自己动手试一下看一看):

      

      7.常用的存储数据的方法

      ⑴向对象栈中存数据,即ValueStack中的root(CompoundRoot)对象 

       * 先得到root,再把数据压入到root中,这中方式是放入到栈底.
                    ValueStack valueStack = ActionContext.getContext().getValueStack();
                    valueStack.getRoot().add(new Person());
            * 先得到root,利用add(index,Object)把一个对象压入到root中指定位置.
                    ValueStack valueStack = ActionContext.getContext().getValueStack();
                    valueStack.getRoot().add(0,new Person());//这里0,表示压入栈顶.
            * 存放一个map到对象栈中
                    ValueStack valueStack = ActionContext.getContext().getValueStack();
                    valueStack.set("msg","dude"); //先封装成Map,在把Map放入到对象栈中,且放入栈顶.
            * 利用valueStack的push方法把一个对象直接压入栈顶
                    ValueStack valueStack = ActionContext.getContext().getValueStack();
                    valueStack.push(new Person());

      ⑵从值栈中获取数据

          * 通过request,session等向map中存储数据

          ActionContext.getContext().getValueStack().peek();

                    ActionContext.getContext().getValueStack().getRoot().get(0);

      ⑶向map栈中存数据,即ValueStack中的context(OgnlContext)

            * 通过request,session等向map中存储数据
                    ServletActionContext.getRequest().setAttribute("username","joey");
                    ServletActionContext.getSession().put("pwd","123");
            * 直接向map栈中放数据
                    ActionContext.getContext().put("msg","how you doing");   

      8.利用OGNL表达式取ValueStack中的数据
            (1)<s:property />:取栈顶的元素。取Stack Context中的值时,应加#,如<s:property value=“#parameter.t” />
            (2)<s:iterator />:取栈顶的元素。此标签的value属性值无论来自对象栈还是Map栈,都可以不加#前缀(<s:select/>标签也适用),因为此标签在迭代的时候,总是把当前正在迭代的元素放入到栈顶。value可以不写,默认是迭代栈顶元素。

     六、OGNL(Object Graphic Navigatinon Language)对象图导航语言

      OGNL是Struts2中使用的一种表达式语言,它可以用于JSP的标签库中,以便能够方便的访问各种对象的属性;它用于界面将参数传递到Action(并进行类型转换)中,还可以用于struts2的配置文件中。

      下面用一个例子来谈ognl的定义,在这个例子中,我们的LoginAction中有一个User对象,而在User对象中又有一个Address对象,这些对象之间依靠这种类的字段进行关联,或者说是依靠字段属性进行导航,

      (1)值栈中Action的普通属性:<s:property value="username" />

      (2)值栈中Action的普通方法:<s:property value="方法()" />

      (2)值栈中对象的普通属性:<s:property value="user.age" />  //如果自己不new,user.xxx只有传入值才会构造user,需要参数为空的构造函数

                     <s:property value="user.address.city" />

      (3)值栈中对象的普通方法:<s:property value="user.方法()" />

                     <s:property value="user.name.length()" />

      (4)静态方法: <s:property value="@全类名@方法()" />  //在某些版本中,struts.ognl.allowStaticMethodAccess的默认值为false,我们只需在struts.xml中增加如下内容:

              <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>

      (5)静态属性: <s:property value="@全类名@属性" />

      (6)默认类Math的访问:<s:property value="@java.lang.Math@min(1,2)"/><br>

                    <s:property value="@@min(1,2)"/><br>

                  <s:property value="@@PI"/>    //因为是默认的类,所以可以省略类名

      (7)普通类的构造方法:<s:property value="new com.dhcc.vo.Student('jack','20','85.5')"/><br>  //只new出对象,显示的时候其实是调用对象的toString方法

                   <s:property value="new com.dhcc.vo.Student('jack','20','85.5').name"/>

      (8)集合对象:

          访问list:<s:property value="users"/>    //[user1,user2,user3]

          访问list中某个元素:<s:property value="users[0]"/>

          访问list中某个属性的集合:<s:property value="users.{age}"/>   

          访问list中某个属性的集合的特定值:<s:property value="users[0].age"/>   |   <s:property value="users.{age}[0]"/>

          访问set:<s:property value="dogs"/>    

          访问set中某个元素:set无序,不能取下标

          访问map:<s:property value="dogMap"/>      //{dog1:d1,dog2:d2}

          访问map中某个元素:<s:property value="dogMap.dog1"/>  或者  <s:property value="dogMap['dog1']"/>

          访问map中所有键:<s:property value="dogMap.keys"/><br>

          访问map中所有值:<s:property value="dogMap.values"/><br>

          访问容器的大小:<s:property value="users.size()"/><br>  //不加()也可以

      (9)投影:?#是指取出符合条件的所有Student对象,而^#是指取出符合条件的第一个对象,$#是指取出符合条件的最后一个对象。

          选择年龄等于20的user信息:<s:property value="users.{?#this.age==20}"/><br>

          选择年龄大于20的user名字信息:<s:property value="users.{?#this.age>20}.{name}"/><br>   

          选择年龄大于20的第一个user名字信息:<s:property value="studentList.{^#this.grade>60}.{name}"/>

                             <s:property value="users.{?#this.age>20}.{name}[0]"/><br>  

          选择年龄大于20的最后一个user名字信息:<s:property value="studentList.{&#this.grade>60}.{name}"/><br>  

      (10)N语法top语法

          N语法[0]<s:property value="[0]"/><br> //[com.dhcc.struts2.action.UserAction@6a35f7e3, com.opensymphony.xwork2.DefaultTextProvider@6239dff6]

          N语法[1]:<s:property value="[1]"/><br>    //[com.opensymphony.xwork2.DefaultTextProvider@6239dff6]

          N语法[0].top:<s:property value="[0].top"/><br>  //com.dhcc.struts2.action.UserAction@6a35f7e3

          N语法[1].top:<s:property value="[1].top"/><br>  //com.opensymphony.xwork2.DefaultTextProvider@6239dff6

          N语法top:<s:property value="top"/><br>    //com.dhcc.struts2.action.UserAction@6a35f7e3

          N语法取值:<s:property value="[0].user.username"/><br>  

          N语法取值:<s:property value="top.user.username"/><br>

         说明:规定栈顶的对象为[0],而我们只使用[0]的意思是从值栈中第一个对象取,一直取至栈底。N的意思是从值栈中的第N个对象开始,取到栈底为止。如果要想访问某个对象,需要使用[N].top,纯top可以简洁地取出值栈中的栈顶对象。当我们通过chain链访问时,值栈中可能有两个以上的Action对象。

       (11)获取Stack Context中的信息

        除了可以从值栈中获取信息,还可以从Stack Context中获取信息,只是要加上#,因为这些对象都是存在一般的Context Map中,而不是存在值栈中。

    名称 

    作用 

    例子 

    parameters

    包含当前HTTP请求参数的Map

    #parameters.id[0]作用相当于request.getParameter("id")

    request

    包含当前HttpServletRequest的属性(attribute)的Map

    #request.userName相当于request.getAttribute("userName")

    session

    包含当前HttpSession的属性(attribute)的Map

    #session.userName相当于session.getAttribute("userName")

    application

    包含当前应用的ServletContext的属性(attribute)的Map

    #application.userName相当于application.getAttribute("userName")

    Attr

    用于按request > session > application顺序访问其属性

    #application.userName相当于application.getAttribute("userName") 

      (12)OGNL总结

        OGNL有一个上下文的概念,这个上下文件实质就是一个Map结构,它实现了java.utils.Map接口,在struts2中上下文的实现为ActionContext,下面是上下文的结构示意图:

        

      当struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action。然后把action存放进ValueStack,所以action的实例变量可以接受OGNL访问。

      访问上下文中的对象需要使用#号标注命名空间,如#application、#session。另外OGNL会设定一个根对象,在struts2中根对象就是ValueStack值栈对象,如果要访问根对象中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。在struts2中,根对象的实现类为OgnlValueStack,该对象不是我们想象的只存放单个值,而是存放一组对象,在OgnlValueStack类里有一个List类型的变量,就是使用这个List变量来存放一组对象。在root变量(List类型)中处于第一位的对象叫栈顶对象,通常我们在Ognl表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下寻找。 注意:struts2中 ,OGNL表达式需要配合struts的标签才可以使用。

    七、struts标签

    7.1通用标签

      添加struts标签库:<%@ taglib uri="/struts-tags" prefix="s" %>

       ①<s:property>

      default:可选属性,如果需要输出的属性值为null,则显示属性指定的值

      escapeHtml:可选属性,指定是否格式化html代码。类似的还有escapeCsv和escapeXml

      value:可选属性,指定需要输出的属性值,如果没有指定该属性,则默认输出ValueStack栈顶的值

    <s:property value="username" default="管理员" /><br/>
    <s:property value="''<hr/>>" escapeHtml="false" />

      ②<s:set>  此标签主要用于设置一些属性值

      scope:指定变量被设置的范围,该属性可以接受applicationsessionrequestpageaction。如果没有设置该属性,则默认放置在OGNL Context中,我们可以通过#号来引用。

      value:赋给变量的值,如果没有设置该属性,则将ValueStack栈顶的值赋给变量。

      var:属性的引用名称,id/name均过时。此名称用于引用push到ValueStack的值

    <s:set var="UserName" value="user.name"/>
    Hello, <s:property value="#UserName"/>
    <s:set var="janesName">Jane Doe</s:set>
    <s:property value="#janesName"/>

     

    posted on 2017-06-30 13:54 ErBing 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/erbing/p/7028616.html

    展开全文
  • struts2教程

    2013-05-20 15:56:48
    找到一个不错的struts2入门教程: Struts2教程1:第一个Struts2程序

    找到一个不错的struts2入门教程:

    Struts2教程1:第一个Struts2程序


    展开全文
  • struts2教程Welcome to Struts 2 Tutorial index post. Struts 2 is one of the mostly used Java Web Application Framework and recently I have wrote a lot about it. Struts 2 is built on top of Struts1 and ...

    struts2教程

    Welcome to Struts 2 Tutorial index post. Struts 2 is one of the mostly used Java Web Application Framework and recently I have wrote a lot about it. Struts 2 is built on top of Struts1 and WebWork framework that makes it highly flexible, extendable and easy to maintain.

    欢迎使用Struts 2教程索引文章。 Struts 2是最常用的Java Web应用程序框架之一,最近我写了很多关于它的文章。 Struts 2建立在Struts1和WebWork框架的基础上,使其高度灵活,可扩展且易于维护。

    Struts 2教程 (Struts 2 Tutorial)

    If you want to learn Struts 2 and it’s important features then please read all the below articles in order. All these articles provide framework features in great details and comes with downloadable web application projects.

    如果您想学习Struts 2及其重要功能,请按顺序阅读以下所有文章。 所有这些文章都提供了非常详细的框架功能,并附带了可下载的Web应用程序项目。

    Struts 2初学者教程 (Struts 2 Tutorial for Beginners)

    1. Struts 2 Example for BeginnersThis is the first article in the series, here you will learn about basics of Struts 2 with brief details about it’s architecture, framework core concepts such as Interceptors, OGNL, Action, Results, wiring the application components etc. The article also provides basic example of Struts 2 web application project with XML based configuration.

      Struts 2入门示例这是该系列的第一篇文章,您将在这里了解Struts 2的基础知识,并简要了解Struts 2的体系结构,框架核心概念(例如,拦截器,OGNL,Action,结果,连接应用程序组件等)。本文还提供了具有基于XML配置的Struts 2 Web应用程序项目的基本示例。
    2. Struts 2 Annotations Example ProjectJava Annotations are becoming popular in most of the Java EE frameworks and Struts 2 provides a lot of annotations that we can use to create Struts 2 web application with zero configuration i.e. without having struts configuration file. Check out the article to learn about the commonly used annotations in Struts 2 framework. The article also provides an example project built with annotations and without having any struts configuration file that you can download and play around.

      Struts 2注释示例项目 Java注释在大多数Java EE框架中变得越来越流行,并且Struts 2提供了许多注释,我们可以使用它们创建零配置(即没有struts配置文件)的Struts 2 Web应用程序。 查看文章以了解Struts 2框架中的常用注释。 本文还提供了一个使用批注构建的示例项目,而没有可供下载和播放的任何struts配置文件。
    3. Struts 2 Result Path ConfigurationWe can configure Struts 2 application to look for result pages at specific location, the article provide brief details about this using XML based configuration as well as annotation based.

      Struts 2结果路径配置我们可以配置Struts 2应用程序以在特定位置查找结果页面,本文使用基于XML的配置以及基于注释的方法提供有关此结果的简短详细信息。
    4. Struts 2 No result defined for action and result inputA common error faced while working with Struts 2 application because of validation failure and there is no result configured for “input” in struts configuration file.

      Struts 2没有为操作和结果输入定义结果由于验证失败,在Struts 2应用程序中使用时会遇到一个常见错误,并且在struts配置文件中没有为“输入”配置任何结果。

    Struts 2动作 (Struts 2 Action)

    1. Struts 2 Action ClassesAction classes are at the front of our application and we invest a lot of time in designing and developing action classes. The article explains about four different ways to create action classes in Struts 2 framework. Learn about these ways and which is the good option to chose in your application action classes.

      Struts 2动作类动作类在我们的应用程序中处于领先地位,我们在设计和开发动作类上投入了大量时间。 本文介绍了在Struts 2框架中创建动作类的四种不同方法。 了解这些方法,这是在应用程序操作类中选择的不错的选择。
    2. Struts 2 Action Object-backed and ModelDriven ExampleMost of the times we don’t want form bean properties to be part of action classes and we want to have them in a java bean that we can use in action classes. There are two approaches to achieve this – Object-backed and ModelDriven. The article explains about both of these approaches and which is the best approach to use.

      Struts 2动作对象支持和ModelDriven示例在大多数情况下,我们不希望表单bean属性成为动作类的一部分,我们希望将它们包含在可用于动作类的java bean中。 有两种方法可以实现这一点-对象支持和模型驱动。 本文介绍了这两种方法,以及哪种方法是最佳使用方法。
    3. Struts2 Action Messages and Action Errors ExampleWe can override ActionSupport validate() method to have form field validation at server side and return the input page with action error messages to show in result pages. Similarly we can add action messages to show in result pages.

      Struts2操作消息和操作错误示例我们可以重写ActionSupport validate()方法以在服务器端进行表单字段验证,并返回输入页面以及操作错误消息以显示在结果页面中。 同样,我们可以添加操作消息以显示在结果页面中。

    Struts 2拦截器 (Struts 2 Interceptors)

    1. Struts 2 Interceptor Tutorial with Custom Interceptor ExampleStruts2 interceptors are the backbone of the framework and defined in struts-default package. Struts2 interceptors are great example of Chain of Responsibility pattern implementation. This article explains about the working of interceptors and how easily we can create our own interceptor and configure it for action. The article shows how we can achieve authentication across the application with the use of custom interceptors and make our code loosely coupled and achieve flexibility with code reuse.

      带自定义拦截器示例的Struts 2拦截器教程 Struts2拦截器是框架的基础,并在struts-default程序包中定义。 Struts2拦截器是责任链模式实现的一个很好的例子。 本文介绍了拦截器的工作原理,以及我们如何轻松地创建自己的拦截器并对其进行配置以进行操作。 本文说明了如何使用自定义拦截器在整个应用程序中实现身份验证,并使我们的代码松耦合,并通过代码重用实现灵活性。
    2. Struts2 token interceptorWe can use Struts2 token and tokenSession interceptors to handle multiple form submission problem at server side in the web application. This article explains about these interceptors in detail with a working example.

      Struts2令牌拦截器我们可以使用Struts2令牌和tokenSession拦截器在Web应用程序的服务器端处理多种表单提交问题。 本文通过一个有效的示例详细说明了这些拦截器。
    3. Struts2 execAndWait interceptorWe can use Struts2 execAndWait interceptor to return an intermediate response page to client incase of long running action classes. Once the action class execution is finished, the final response is returned to the client. This article explains about execAndWait interceptor and how can we use this for long running action classes.

      Struts2 execAndWait拦截器如果长时间运行的动作类,我们可以使用Struts2 execAndWait拦截器将中间响应页面返回给客户端。 动作类执行完成后,最终响应将返回给客户端。 本文介绍了execAndWait拦截器,以及如何将其用于长时间运行的动作类。

    Struts 2的标签 (Struts 2 Tags)

    1. Struts 2 OGNL TutorialStruts2 uses OGNL expression language for data transfer from request to action classes bean properties and type conversion from String to objects and vice versa in result pages. The article provide details about the usage of OGNL expressions and how we can create our own type converter classes.

      Struts 2 OGNL教程 Struts2使用OGNL表达式语言从请求到动作类bean属性进行数据传输,并在结果页面中从String到对象进行类型转换,反之亦然。 本文提供有关OGNL表达式的用法以及如何创建自己的类型转换器类的详细信息。
    2. Struts2 Data TagsStruts2 comes with rich tags that can be categorized into data, control and UI tags. This article provide details about majorly used Struts2 data tags with example project.

      Struts2数据标签 Struts2带有丰富的标签,可以将其分类为数据,控件和UI标签。 本文提供有关示例项目中常用的Struts2数据标签的详细信息。
    3. Struts2 Control TagsStruts2 control tags are used for manipulation and navigation of data from a collection. This article provide details about the Struts2 control tags and how we can use them for conditional flow and iterate over an array or collection. We also learn about some other control tags used to sort list, merge lists, append lists and take subset of list with example project.

      Struts2控件标签 Struts2控件标签用于操作和导航集合中的数据。 本文提供有关Struts2控件标签的详细信息,以及如何将它们用于条件流以及如何在数组或集合上进行迭代。 我们还将了解其他一些控制标签,这些标签用于对示例项目进行排序,合并列表,追加列表以及获取列表子集。
    4. Struts2 UI TagsStruts2 UI tags are used to generate HTML form elements in result pages. UI tags are also responsible for binding form properties to action class properties. This article provide details about mostly used UI tags with example project.

      Struts2 UI标记 Struts2 UI标记用于在结果页面中生成HTML表单元素。 UI标记还负责将表单属性绑定到动作类属性。 本文提供了有关示例项目中最常用的UI标记的详细信息。

    Struts 2本地化 (Struts 2 Localization)

    Struts2 Resource Bundles and Localization

    Struts2资源包和本地化

    Struts2 provides strong support for internationalization through I18nInterceptor and resource bundles. This article explains about i18n support in Struts2 framework with different locations of resource bundles with example project.

    Struts2通过I18nInterceptor和资源包为国际化提供了强大的支持。 本文介绍了示例项目中Struts2框架中i18n支持的不同资源包位置。

    Struts 2教程–其他 (Struts 2 Tutorial – Miscellaneous)

    1. Struts2 Single and Multiple File Upload ExampleFile uploading is one of the common tasks in the web application. That’s why Struts2 provides FileUploadInterceptor interceptor that we can use to upload Single as well as multiple files on the server without using any third party tools. The article explains about this interceptor in detail with example project to upload files on server.

      Struts2单文件和多文件上传示例文件上传是Web应用程序中的常见任务之一。 这就是Struts2提供FileUploadInterceptor拦截器的原因,我们可以使用该拦截器在服务器上上传单个以及多个文件,而无需使用任何第三方工具。 本文详细介绍了有关此拦截器的示例项目,该示例项目可将文件上传到服务器上。
    2. How to get Servlet Session, Request, Response, Context Attributes in Struts 2 ActionSometimes we want to have access to Servlet API components such as Session, Request and Response in action classes. Struts2 provides a bunch of *Aware interfaces that we can implement in action classes to inject Servlet API components in action classes.

      如何在Struts 2 Action中获取Servlet的Session,Request,Response和Context属性有时我们希望访问Servlet API组件,例如Action类中的Session,Request和Response。 Struts2提供了一堆* Aware接口,我们可以在操作类中实现这些接口,以便将Servlet API组件注入到操作类中。
    3. Struts2 and log4j integrationThis article explains how we can integrate log4j with Struts2 framework in our web application for logging purposes.

      Struts2和log4j集成本文介绍了如何将Log4j与Struts2框架集成到Web应用程序中以进行日志记录。
    4. Struts2 Exception HandlingStruts2 provide convenient ways to configure error pages for exceptions thrown by our application at global package level as well as action level. Again this is done by Struts2 exception interceptor that is part of defaultStack. Check out this post for example project with usage details.

      Struts2异常处理 Struts2提供了便捷的方法来配置错误页面,以在全局包级别和操作级别为应用程序抛出的异常进行配置。 同样,这是由DefaultStack的一部分Struts2异常拦截器完成的。 请查看这篇文章,以了解有关使用情况的示例项目。
    5. Struts2 Hibernate Integration ExampleMostly we use an ORM tool in enterprise applications and Hibernate is one of the best choices available in the market. This tutorial provide details about how to integrate Hibernate with Struts2 framework in a web application with downloadable example project.

      Struts2 Hibernate集成示例通常,我们在企业应用程序中使用ORM工具,而Hibernate是市场上最好的选择之一。 本教程提供了有关如何通过可下载的示例项目在Web应用程序中集成Hibernate与Struts2框架的详细信息。

    Struts 2面试题 (Struts 2 Interview Questions)

    This article lists most important Struts 2 interview questions with detailed answers to clear you through interview.

    本文列出了最重要的Struts 2面试问题,并提供了详细的答案,可帮助您通过面试使您清晰。

    There are more articles to come in Struts 2 tutorial series, do bookmark this post for future reference.

    Struts 2教程系列中还会有更多文章,请为这篇文章添加书签以供将来参考。

    翻译自: https://www.journaldev.com/2310/struts-2-tutorial

    struts2教程

    展开全文
  • Struts 2教程

    2020-05-27 09:02:04
    Apache Struts 2是另一个流行的Java Model-View-Contraller(MVC)框架,结合了成功的WebWork和Struts 1.x Web框架。 Apache Struts 2Struts 1完全不同,它的核心功能全部由拦截器,“值堆栈”概念,OGNL表达式...
  • struts 2 教程

    2009-10-26 23:01:16
    不错的资料! 开始学习struts 2
  • STRUTS 2 教程

    2010-11-05 09:40:00
    http://www.360doc.com/content/08/0727/10/70655_1475254.shtml
  • Apache Struts2与Struts1完全不同,它的核心功能都是使用拦截实现“值栈”的概念,OGNL表达式和Struts2标签来解决应用程序数据,很多注解和约定,使这个框架更加易于使用。 在本教程中,它提供了许多使用Struts...
  • struts2教程-学习笔记.zip
  • Struts2教程+所有例子的源代码.zip
  • 第一章 搭建Struts2开发环境Struts2概述在Struts的官方网站上,写着下面两段话:Apache Struts 2 is an elegant, extensible framework for creatingenterprise-ready Java web applications. The framework is ...
  • Struts2 教程 基本MVC架构 Struts2是什么 Struts2开发环境搭建 Struts2 架构 Struts2 HelloWorld Struts2配置文件 Struts2 动作 Struts2 拦截器 Struts2结果和结果类型 Struts2 值栈 OGNL Struts 2文件上传 ...
  • Struts2教程列表

    2014-04-04 09:58:00
    Struts2教程 Struts 2 Interceptors Example In this example you will see how the interceptors are invoked both before and after the execution of the action and how the results ...
  • struts2教程系列

    2013-05-16 14:27:00
    struts2教程系列: http://www.blogjava.net/nokiaguy/archive/2008/04/17/193776.html struts2配置: http://www.cnblogs.com/wchhuangya/archive/2011/03/21/1968877.html struts2配置: ...
  • Struts2教程1:第一个Struts2程序 本文为原创,如需转载,请注明作者和出处,谢谢! 在本系列教程中我们将学习到Struts2的各种技术。在本教程中使用的工具和程序库的版本如下: 开发工具:MyEclipse6 Web...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,669
精华内容 1,067
关键字:

struts2教程