• 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


     

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

  • 相关阅读:
    第一章 初识shiro
    LDAP概念
    css定位
    css随笔1
    自己动手实现信息检索系统
    IntelliJ IDEA和pycharm注册码
    俄罗斯农夫算法
    [NOIP2013]转圈游戏
    [codevs1287]矩阵乘法
    [洛谷1314]无序字母对
  • 原文地址:https://www.cnblogs.com/cuker919/p/4878661.html
Copyright © 2020-2023  润新知