`
rustlingwind
  • 浏览: 21232 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

struts2-rest-plugin 的bug?如果是的话,这个插件的问题可真够多的!

阅读更多
用注释方式给rest controller 加上拦截器:
@InterceptorRefs({@InterceptorRef("authorization"),@InterceptorRef("defaultStack")})

发现加上拦截器后,立马蹦出来一堆怪问题!

该执行的不执行了:
/userinfos/3.xml
在执行show()之前,
本来该执行
setId(String id) 方法,但不执行。
本来不应该执行validate()方法,但竟然执行了!

不加拦截器的时候好好的!
晕死了。。。
如果真是struts2-rest-plugin 的bug,可真够过分的!

——本来怀疑是不是拦截器中 invocation.invoke()执行回调时,RestActionInvocation被替换成了DefaultActionInvocation,导致丢掉了rest的特性,但result仍然返回了xml,理应不是。可如果不是这个原因,又是什么原因呢?


==================================================
2010.2.24 这个问题解决了!
==================================================
今天上午忽然发现弄了半天是引用的拦截器栈的名字写错了!
但这个问题背后,其实是我对问题的本质没有理解。刚开始就想到会不会是 actionInvocation 由 restActionInvocation 被替换成了
DefaultActionInvocation所致。但却没往拦截器方面去想。
仔细看了一下 struts2-rest-plugin jar包里的 struts-plugin.xml,里面有个 "restDefaultStack",我继承人家的"rest-default"package,在引用人家的默认拦截器栈时,当然不应该引用传统的"defaultStack",而应该引用rest包的"restDefaultStack",这样id参数自然不会丢失了,validate方法的执行也不会有问题了——show/index都不会执行,update/create 都默认执行。

但是还有个问题。。。


==================================================
2010.2.24 新问题!
==================================================

我想给 controller 中的方法添加拦截器,并且希望拦截器能加在 method 级别上。
看了 convension plugin 的官方文档:
http://struts.apache.org/2.x/docs/convention-plugin.html#ConventionPlugin-Applying@Actionand@Actionsattheclasslevel
所幸文档写的很明确,是支持的!
但是按照文档的样子,照搬到 rest 方式的 controller 上,却有问题!
一段代码:
// PUT /orders/1
    //@Action(interceptorRefs={@InterceptorRef("authorizationStack")})
    @Action(interceptorRefs={@InterceptorRef("authorization"), @InterceptorRef("restDefaultStack")})
    public String update() {
        ordersService.save(model);
        addActionMessage("Order updated successfully");
        return "success";
    }

// GET /orders/1
    public HttpHeaders show() {
        return new DefaultHttpHeaders("show");
    }

    // GET /orders
    public HttpHeaders index() {
        list = ordersService.getAll();
        return new DefaultHttpHeaders("index")
            .disableCaching();
    }

本以为肯定只是拦截 update方法的,但当我访问show或index方法时,拦截器也一样都执行了!
百思不得其解!
所幸又从网上看到了这篇帖子:
http://topic.csdn.net/u/20091214/11/15a63547-92b6-448e-8ddf-143fe3d243f8.html
但该文中提到的是关于convention plugin 方式的,对于rest plugin来说,有其特殊的地方,就是无法给action添加自定义的名字——@Action(value="xxx");

rest方式下,如果要执行controller的update方法,会这样:
PUT /userinfos/{id}.xml
然后会执行对应controller中的update方法。也就是说,rest方式不会要求指定方法的名字。如果我硬给update指定一个:
@Action(value="update"),会报错!提示找不到对应的action。

难道rest方式下就没有办法将拦截器添加到method级别上么?郁闷。。。




1
0
分享到:
评论
3 楼 rustlingwind 2010-02-24  
mht19840918 写道
忘了说了,你还是没有搞清楚Struts2拦截器的原理,还是要好好看看。Struts2 rest本身就是借助拦截器实现的,所以你这个问题与rest一点关系都没有
最后补充下上面CardToken标记代码:

@Retention(RetentionPolicy.RUNTIME)
@Target( {
    ElementType.METHOD
})
public @interface CardToken {
}

呵呵,非常感谢!我还跟琨哥说让他代我谢谢你!
真有一种雪中送碳的感觉,这个问题已经困扰我一天了!

看过你的回复,我已经明白了你的意思。用自定义注释的方式,借助struts2的拦截器思想,来完成对 action的过滤。

我马上试一下!
2 楼 mht19840918 2010-02-24  
忘了说了,你还是没有搞清楚Struts2拦截器的原理,还是要好好看看。Struts2 rest本身就是借助拦截器实现的,所以你这个问题与rest一点关系都没有
最后补充下上面CardToken标记代码:

@Retention(RetentionPolicy.RUNTIME)
@Target( {
    ElementType.METHOD
})
public @interface CardToken {
}
1 楼 mht19840918 2010-02-24  
受朋友之托,简单说下:
1、我讨厌用注释方式配拦截器,所以少了直接陪在struts.xml中代码如下:
<package name="card" extends="rest-default">
    <interceptors>
      <interceptor name="exceptionInterceptor" class="com.fost.card.webcommon.ExceptionInterceptor" />
      <interceptor name="token" class="com.fost.card.webcommon.token.TokenInteceptor" />
      <interceptor name="validateInterceptor" class="com.fost.card.webcommon.validate.CardValidateInteceptor" />
      <interceptor-stack name="cardDefaultStack">
        <interceptor-ref name="servletConfig" />
        <interceptor-ref name="token" />
        <interceptor-ref name="prepare" />
        <interceptor-ref name="actionMappingParams" />
        <interceptor-ref name="modelDriven">
          <param name="refreshModelBeforeResult">true</param>
        </interceptor-ref>
        <interceptor-ref name="fileUpload" />
        <interceptor-ref name="staticParams" />
        <interceptor-ref name="params">
          <param name="excludeParams">dojo\..*</param>
        </interceptor-ref>
        <interceptor-ref name="rest" />
        <interceptor-ref name="conversionError" />
        <interceptor-ref name="validateInterceptor" />
        <interceptor-ref name="restWorkflow">
          <param name="excludeMethods">input,back,cancel,browse,index,show,edit,editNew</param>
        </interceptor-ref>
        <interceptor-ref name="exceptionInterceptor" />
      </interceptor-stack>
    </interceptors>
    <default-interceptor-ref name="cardDefaultStack" />
    <global-results>
      <result name="error" type="dispatcher">/WEB-INF/jsp/error.jsp</result>
    </global-results>
  </package>
如上,有exceptionInterceptor,CardValidateInteceptor,TokenInteceptor是自定义拦截器。
2、挣对你的情况,开发个@interface最好,在拦截的方法上打个标签如:
    @Validate //验证拦截器
    public String create() {
        log.debug("create order!");

        return "success";
    }
拦截器当拦截到请求会先根据标签判断是不是需要处理的。
3、自定义拦截器
public class TokenInteceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        String method = invocation.getProxy().getMethod();
        Object action = invocation.getAction();
        // 获取当前调用的方法
        Method invokeMethod = action.getClass().getMethod(method, new Class[] {});
        if ("POST".equals(request.getMethod()) && StringUtils.isNotBlank(method)
                && invokeMethod.isAnnotationPresent(CardToken.class)) {
            // 获取请求中的TOKEN
            String token = request.getParameter(GenerateToken.COMMIT_TOKEN);
            // 如果有TOKEN,说明需要进行表单重复提交验证
            if (!StringUtils.isBlank(token)) {
                PrintWriter writer = null;
                try {
                    if (!validToken(token)) {
                        HttpServletResponse resp = ServletActionContext.getResponse();
                        writer = resp.getWriter();
                        writer.write(TIPS_MSG);
                        return null;
                    }
                } catch (Exception e) {
                    throw new CardRunException(e);
                } finally {
                    IOUtils.closeQuietly(writer);
                }
            } else {
                throw new CardRunException("token使用非法,post提交数据中,没有发现参数" + GenerateToken.COMMIT_TOKEN + ",或参数"
                        + GenerateToken.COMMIT_TOKEN + "为空");
            }

        }
        return invocation.invoke();
    }


}

如上invokeMethod.isAnnotationPresent(CardToken.class))就是处理标记的方法,希望对你有帮助。

相关推荐

    struts2-rest-plugin-2.1.6.jar

    struts2-rest-plugin-2.1.6.jar

    struts2-json-plugin-2.3.8.jar

    Struts2 JSON Plugin是针对Apache Struts2框架的一个重要组件,版本为2.3.8。这个插件主要的功能是让Struts2应用程序能够轻松地处理JSON(JavaScript Object Notation)数据格式,使得Web应用可以方便地进行JSON序列...

    struts2-json-plugin-2.3.24-API文档-中文版.zip

    赠送jar包:struts2-json-plugin-2.3.24.jar; 赠送原API文档:struts2-json-plugin-2.3.24-javadoc.jar; 赠送源代码:struts2-json-plugin-2.3.24-sources.jar; 赠送Maven依赖信息文件:struts2-json-plugin-...

    Struts2-rest插件(有注释)

    由于 Struts 2 的 Convention 插件的主要特点是“约定优于配置”,当我们已经习惯了 Struts 2 的基本开发方法之后,如果希望改为使用 Convention 插件也非常容易,我们只要放弃 Stuts 2.1 应用原有的配置文件,改为...

    struts2-json-plugin

    struts2-json-plugin,Struts JSON插件

    struts2-spring-plugin-2.3.15.2.jar ; struts2-json-plugin-2.3.16.3.jar

    struts2-spring-plugin-2.3.15.2.jar ; struts2-json-plugin-2.3.16.3.jarstruts2-spring-plugin-2.3.15.2.jar ; struts2-json-plugin-2.3.16.3.jar

    struts2-ssl-plugin-1.2.1.jar

    struts2-ssl-plugin-1.2.1.jar

    struts2-struts1-plugin-2.1.6.jar

    struts2-struts1-plugin-2.1.6.jar

    struts2-spring-plugin-2.3.4.jar

    Struts2-Spring-Plugin-2.3.4.jar 是一个专门为 Struts 2 框架和 Spring 框架整合而设计的插件,主要用于处理 Struts 2 和 Spring 之间的集成问题。在Java Web开发中,这两个框架经常一起使用,Spring 提供了依赖...

    struts2-convention-plugin-2.1.6.jar

    struts2-convention-plugin-2.1.6.jar

    struts2-dojo-plugin-2.2.1.jar

    这个插件是Struts2与Dojo Toolkit的桥梁,使得开发者能够轻松地在Struts2应用中利用Dojo的强大功能。 Struts2是一个流行的开源MVC(Model-View-Controller)框架,用于构建Java web应用程序。它提供了良好的架构...

    Struts2开发常用jar包

    core-2.5.10.1.jar,struts2-jfreechart-plugin-2.5.10.1.jar,struts2-json-plugin-2.5.10.1.jar,struts2-junit-plugin-2.5.10.1.jar,struts2-bean-validation-plugin-2.5.10.1.jar,struts2-cdi-plugin-...

    struts2-spring-plugin-2.2.1.jar

    Struts2-Spring-Plugin-2.2.1.jar 是一个专门为 Struts2 框架与 Spring 框架集成而设计的插件。这个插件的主要目的是简化在基于Struts2的应用程序中整合Spring的功能,如依赖注入(DI)、AOP(面向切面编程)以及...

    struts2-dojo-plugin-2.3.4 jar

    struts2-dojo-plugin-2.3.4 jar 日期控件的jar包 需要的自行下载

    json-lib-2.1.jar和struts2-json-plugin-2.1.8.1.jar

    `struts2-json-plugin-2.1.8.1.jar` 则是Struts 2框架的一个插件,主要用于增强Struts 2对JSON的支持。Struts 2是一款非常流行的MVC(Model-View-Controller)框架,用于构建企业级的Java Web应用程序。这个插件允许...

    struts2-struts1-plugin-2.1.8.1.jar

    最新struts2-struts1-plugin-2.1.8.1.jar

    Struts2-3.24集合jar

    struts2-config-browser-plugin-2.3.24.jar, struts2-core-2.3.24.jar, struts2-jasperreports-plugin-2.3.24.jar, struts2-jfreechart-plugin-2.3.24.jar, struts2-pell-multipart-plugin-2.3.24.jar, struts2-...

    struts2-json-plugin源码

    Struts2是一个非常流行的Java Web框架,用于构建可维护、可扩展且结构良好的应用程序。它提供了MVC(Model-View-Controller)架构模式的支持,帮助开发者有效地管理业务逻辑、数据展示和用户交互。JSON(JavaScript ...

    struts-json-plugin-2.1.8.jar struts2-junit-plugin-2.1.8.jar json-lib-2.1.jar

    如果您的项目中使用了Struts2并且需要与JSON数据交互,这个插件是必不可少的。 接着是`struts2-junit-plugin-2.1.8.jar`,这是一个用于Struts2的JUnit测试插件。它扩展了JUnit,使得Struts2的控制器可以在单元测试...

    struts2-convention-plugin-2.3.24.1

    struts2-convention-plugin-2.3.24.1

Global site tag (gtag.js) - Google Analytics