zoukankan      html  css  js  c++  java
  • Struts 2.0的codebehinde插件应用简述

    codebehind plugin是一个可以简化struts2配置的插件,虽然不能实现完全意义上的codebehind,至少已经做的不错了,期待新版本:-D

    使用步骤:

    1.确保你的应用已经可以使用struts2

    2.添加struts2-codebehind-plugin-2.0.11.2.jar包到应用中

    3.struts.xml中添加配置:<constant name="struts.codebehind.pathPrefix" value="/jsp/" /> 这里的value值填写jsp页面的根路径

    然后就可以使用了,在不使用codebehind插件的时候,一般是这么写的:

    <action name="userlist" class="userListAction">    <result>/jsp/userlist.jsp</result></action>使用codebehind插件的话,可以这么写:

    <action name="userlist" class="userAction" />result可以省略了,当然这里有一个约定,返回页面的路径为struts.codebehind.pathPrefix + package namespace + action name + action returntype + .jsp

    我这里的环境:

    struts.codebehind.pathPrefix  = /jsp/

    package namespace = /

    action name = userlist

    action returntype = 为success时,值为空,为其他时,值为"-" + return type

    所以返回的页面地址就为 /jsp/userlist.jsp

    如果return type为input,地址就为 /jsp/userlist-input.jsp

    配合表达式的使用,可以基本实现零配置:

    <action name="*" class="{1}Action" />这样写不仅可以简化配置,而且可以达到规范文件布局的目的。如果有特殊的需要,也完全可以与手写配置文件相结合,用起来已经很方便了。

    Struts 2.0 的codebehind插件

    1.添加struts2-codebehind-plugin-2.0.11.2.jar包到应用中

    2.struts.xml中添加配置:<constant name="struts.codebehind.pathPrefix" value="/XXX/" />

    说明:value的值从项目的根路径开始写。以“/”结尾。

    返回页面的路径为struts.codebehind.pathPrefix + package_namespace + action_name + action_execute_returnString + .jsp

    例如:

    struts.codebehind.pathPrefix  = /WEB-INF/jsp/

    package_namespace = /haohaibo

    action_name = hello

    action_execute_returnString  为success时,值为空,为其他时,值为"-" + action_execute_returnString

    如果:Action类中的 execute() 方法的返回值是:“SUCCESS“,

    则显示的页面就是:/WEB-INF/jsp/haohaibo/hello.jsp

    Action类中的 execute() 方法的返回值是:“error“,

    则显示的页面就是:/WEB-INF/jsp/haohaibo/hello-error.jsp

    用codebehind插件的时候,在存放页面的地方一定要有和namespace对应的文件夹,不然的话,显示页面的时候会找不到页面而报错。

     

     

     

    SpringSide 3 中的 Struts 2

    在SpringSide 3 中,使用的MVC框架是Struts 2。Struts 2 向对于Struts 1 来说,具有相当多的优点,有很多人都说,用过Struts 2之后,再也不想看Struts 1了。然而,任何东西都有它的复杂性,Struts 2也不例外,SpringSide 3做了很多工作来简化Struts 2 的使用。

    先来说说Struts 2的特点:
    1、编写Action变得简单了,Action变成了简单的POJO,再也不用和ActionForm、ActionForward打交道了,返回的时候直接返回字符串即可。如果要访问Servlet API,则直接使用ServletActionContext类的静态方法。
    2、Struts 2提供了插件机制,允许我们自己为它编写插件,当然,要我自己写是不现实的,但是面对别人写的琳琅满目的插件,我一样会昏头。再网上随便一搜,就可以发现40多种Struts 2插件。SpringSide 3选择的CodeBehind,就是一种Struts 2插件,它的目的是为了简化配置。
    3、Struts 2提供了拦截器机制,之所以编写Action的任务那么简单,靠的都是这些拦截器,比如它们可以自动解析Web表单和URL参数,把它们注入到Action中。
    4、Struts 2提供了丰富的taglib,当然,丰富也代表着我们要化更多的时间去学习。
    5、Struts 2依然提供了Validator和i18n支持。
    等等...

    下面,我们来看看SpringSide 3是怎么使用Struts 2的吧。SpringSide 3的主要目标是降低我们使用Struts 2的复杂性,所以,它选择了这些办法:
    1、没有使用Validator和i18n,对数据的验证交给了JQuery,这变成了表现层的任务,而且JQuery也可以使用AJAX从服务器端进行验证。至于i18n,江南白衣说小网站用不上。
    2、没有使用Struts 2的UI标签,当然也就没有使用FreeMaker或SiteMesh了。

    当然,省掉了一些东西,就省掉了我们不少的学习时间。对于Struts 2核心的一些东西,我们看看它是怎么做的:

    1、使用CodeBehind插件来简化配置。使用CodeBehind后,我们就可以不用配置result了,它可以根据我们Action的返回值自动猜测返回的视图页面,它猜测的规则是这样的:返回页面的路径为struts.codebehind.pathPrefix + package namespace + action name + action returnvalue + .jsp,action returnvalue为success时,值为空,为其他时,值为"-" + return type。我们来看看SpringSide 3生成的项目中关于Struts 2的配置文件:

    其中struts.codebehind.pathPrefix设置为“/WEB-INF/jsp/”,package的namespace没有设置,所以,如果我们的Action为UserAction,则返回success时,就会返回到/WEB-INF/jsp/user.jsp,如果返回input,则返回到/WEB-INF/jsp/user-input.jsp。这里江南白衣玩了一个狡猾,他把所有的jsp页面放到WEB-INF目录中,别人就没有办法直接访问了,这样就可以简化Acegi的配置工作。

    2、关于拦截器栈
    在上面讲Struts 2的特点时,我已经说了Struts 2中拦截器的重要作用,在上面的截图中,package的配置没有做别的什么事,主要就是配置了拦截器栈。那么拦截器栈是怎么使用的呢?它是在Action类中通过@ParentPackage指定的,如下面的代码:


    下面,我来具体说一下拦截器有什么作用。
    例子一、我们知道Struts 2中的Action是和Servlet API解耦的,那么如果我们要在Action中访问Servlet API怎么办呢?一种办法就是使用ServletActionContext,如下图:

    另外一种办法,就是让我们的Action实现ServletRequestAware接口,如下代码:

    public   class MyAction implements ServletRequestAware {
        private HttpServletRequest request;
        public   void setServletRequest(HttpServletRequest request) {
             this .request = request;
       }
        public String execute() throws Exception {
             // do the work using the request
             return Action.SUCCESS;
       }
    }
    这时候,ServletConfigInterceptor 拦截器就会把request对象注入到我们的Action中。

    例子二、ParametersInterceptor 拦截器会自动解析web表单或URL参数,并把它们注入到Action中。但是很多时候,我们不愿意我们的Action具有太多的属性,因为一大堆的get、set方法看起来太乱糟糟,我们希望有一个专门的Model对象来存储这些值,而且刚好我们为Hibernate设计的Entity类用来做Model正合适。这时,我们可以让我们的Action实现ModelDriven接口,让getModel()方法返回我们的entity对象即可。这正是SpringSide 3采取的方法,如下图的代码片断:


    这时候,ModelDrivenInterceptor拦截器就会帮助我们把解析的URL参数或表单数据注入到entity的属性中,而不是Action中。

    例子三、Preparable 接口联合PrepareInterceptor拦截器一起工作,可以让action在执行execute() 方法前, 执行一个prepare()方法,这也正是SpringSide 3的工作方式。

    3、关于Action
    有了上面对CodeBehind的理解和对拦截器栈的理解后,再来理解SpringSide 3中的Action就再简单不过了,SpringSide 3中Action的继承树如下:

    其中ActionSupport类是Struts 2提供的,另外两个类是白衣自己扩展的。其中SimpleActionSupport主要是提供了一些绕过jsp页面直接输出字符串的方法,不值一谈。而CRUDActionSupport就比较复杂,如下:
    public abstract class CRUDActionSupport<T> extends SimpleActionSupport implements ModelDriven<T>, Preparable {
        /**
         * 进行CUD操作后,以redirect方式重新打开action默认页的result名.
         */
        public static final String RELOAD = "reload";

        /**
         * Action函数,默认action函数,默认指向list函数.
         */
        @Override
        public String execute() throws Exception {
            return list();
        }

        /**
         * Action函数,显示Entity列表.
         * return SUCCESS.
         */
        public abstract String list() throws Exception;

        /**
         * Action函数,新增或修改Entity.
         * return RELOAD.
         */
        public abstract String save() throws Exception;

        /**
         * Action函数,删除Entity.
         * return RELOAD.
         */
        public abstract String delete() throws Exception;

        /**
         * 在save()前执行二次绑定.
         */
        public void prepareSave() throws Exception {
            prepareModel();
        }

        /**
         * 在input()前执行二次绑定.
         */
        public void prepareInput() throws Exception {
            prepareModel();
        }

        /**
         * 屏蔽公共的二次绑定.
         */
        public void prepare() throws Exception {
        }

        /**
         * 等同于prepare()的内部函数.
         */
        protected abstract void prepareModel() throws Exception;
    }

    第一,它做了把CRUD操作放到了同一个Action中的操作,这样可以少写几个Action。这个工作难度不大,我觉得白衣此举,主要是为了规范CRUD函数的命名。在Struts 2中,如果我们要访问的不是默认的excute方法,可以使用如/user!save.action的格式,这样访问的就是UserAction的save方法。
    第二,它实现了ModelDriven接口和Preparable接口,关于这两个接口,我在前面讲拦截器的时候已经提到过了,所以很容易理解。我们可以把我们为Hibernate设计的entity类作为Model,也可以把初始化这些entity的工作放到prepareSave()和prepareInput()方法中,这两个方法将会在save()和input()方法执行前自动执行。
    第三,它定义了一个静态变量RELOAD,定义这个变量的目的是为了定义一个result的需要。CodeBehind中,大部分的result可以自己猜测,对于不能猜测的,需要使用@Results指定,如下代码:

    好了,对SpringSide 3中Struts 2的分析就写到这里了。总之,使用SpringSide 3时,对于Action这一块非常简单,如果不设及到CRUD操作,就继承SimpleActionSupport,如果涉及到CRUD操作,就继承CRUDActionSupport,并在getModel()/save()/prepareSave/input()/prepareInput()等框框中填入适当的代码即可。

    最好是在Java源代码也以namespace建立一个source Folder,这样看起来会比较清晰一点!

    web.xml配置文件

    1. <filter>  
    2.   <filter-name>struts2</filter-name>  
    3.   <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  
    4.   <init-param>  
    5.     <param-name>actionPackages</param-name>  
    6.     <param-value>demo.actions1,demo.actions2</param-value>  
    7.   </init-param>  
    8. </filter> 

     Action and Package name
    Struts2扫描到Action后,从actionPackages指定的包开始,子包名 会成为这个Action的namespace,而Action的name则由这个Action的类名决定。将类名首字母小写,如果类名以Action结 尾,则去掉"Action"后缀,形成的名字就是这个Action的名字。在如上所述的示例中,actionPackages指定为 demo.actions1,demo.actions2,那么你可以这样访问 demo.actions1.app.person.ListPeopleAction:
    http://localhost:8080/app/person/listPeople


     

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    PAT 1010. 一元多项式求导 (25)
    PAT 1009. 说反话 (20) JAVA
    PAT 1009. 说反话 (20)
    PAT 1007. 素数对猜想 (20)
    POJ 2752 Seek the Name, Seek the Fame KMP
    POJ 2406 Power Strings KMP
    ZOJ3811 Untrusted Patrol
    Codeforces Round #265 (Div. 2) 题解
    Topcoder SRM632 DIV2 解题报告
    Topcoder SRM631 DIV2 解题报告
  • 原文地址:https://www.cnblogs.com/cuker919/p/4878661.html
Copyright © 2011-2022 走看看