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

挥之不去的噩梦,struts2 rest 的通病

阅读更多
话说前天碰到的问题,已经被一个好心的eye友给轻松解决了。真的非常感谢。
但今天又碰到一个问题。
而且跟前天碰到的其实应该是一类问题。

前天问题的解决方法,其实是换了一种途径。但我当时想用的方法为什么不行,我还是不清楚。
@Action(interceptorRefs={@InterceptorRef("authorization"), @InterceptorRef("restDefaultStack")})
    public String update() {
        ordersService.save(model);
        addActionMessage("Order updated successfully");
        return "success";
    }

就是说,拦截器不能直接加在 method level 上面,而只能加在 Action.class级别。
问题的原因不清楚,但我想或许与没有指定 @Action(value="xxx")的value值有关!

如果只是使用struts2 的 convention 插件,当然可以指定value,但是rest方式下,标准的那7个方法如何指定别名呢?即便能够指定,也很奇怪!

为何说今天遇到的问题类似。因为我在完善action的返回值的处理的时候,发现Result竟然也无法加在method level上,而只能是 action.class上,与拦截器的问题一样。

代码如下:

  @Action(
        results={@Result(name="exception", type="httpheader", params={"status", "503", "errorMessage", "Internal Error"})}
    )
    public HttpHeaders show() {
        int i = 1/0;
        return new DefaultHttpHeaders("show").disableCaching();
    }
   
    @Action(results={@Result(name="exception", type="httpheader", params={"status", "504", "errorMessage", "Internal Error"})})
    public HttpHeaders index() {
        int i = 1/0;
        list = ordersService.getAll();
        return new DefaultHttpHeaders("index").disableCaching();
    }

与官方文档对照再三,唯一的区别就是我没有指定 @Action 的 value 属性。
给上面这段代码的 @Action 加上 value 属性,果然不出所料。

本来下面的url可以访问某个order:
/orders/3.xml
如果添加了value,就只能写成:
/orders/show/3.xml   --> @Action(value="/orders/show/")

这还叫rest么?

不明白,难道 struts2 rest plugin 就没办法指定 method level 的 Result 么?还有拦截器,也有这个问题。其实还有异常声明,也是。@ExceptionMapping也没法直接加在method level上,官方文档说行,那也是 Convention plugin ,换成rest,都不行了。

难道一点辙都没了?那我的程序该咋办啊,异常处理/返回结果值处理 都没法弄了。。。
狂晕中,老板让俺今天把这块儿东西做完,可是这个问题就像钉在那里一样,一点都无计可施。。。我的希望全寄托在mht19840918老兄身上了,盼大师能给在下指点一下迷津!
1
1
分享到:
评论
8 楼 rustlingwind 2010-03-02  
mht19840918 写道
刚看了下源码,说说现在最笨的办法,这个只对比较简单的返回,rest插件也就是拦截url的后缀(.以后的),也就是.json/.xml/.xhtml默认xhtml,你也在拦截器中而外识别下访问的后缀,
预备三套返回模板,如:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>NoSuchKey</Code>
  <Message>The resource you requested does not exist</Message>
  <Resource>/mybucket/myfoto.jpg</Resource>
  <RequestId>4442587FB7D0A2F9</RequestId>
</Error>
or
json
or
xhtml
然后Response的writer出去,比较复杂的返回建议改源码


OK,终于盼到您的回复了!呵呵!我今天晚上就试试!下午把其他的写完。谢谢哈~
7 楼 mht19840918 2010-03-02  
刚看了下源码,说说现在最笨的办法,这个只对比较简单的返回,rest插件也就是拦截url的后缀(.以后的),也就是.json/.xml/.xhtml默认xhtml,你也在拦截器中而外识别下访问的后缀,
预备三套返回模板,如:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>NoSuchKey</Code>
  <Message>The resource you requested does not exist</Message>
  <Resource>/mybucket/myfoto.jpg</Resource>
  <RequestId>4442587FB7D0A2F9</RequestId>
</Error>
or
json
or
xhtml
然后Response的writer出去,比较复杂的返回建议改源码
6 楼 mht19840918 2010-03-02  
这个恐怕要看下源代码了,我最近项目赶的紧,实在帮不上你
5 楼 rustlingwind 2010-02-27  
mht19840918 写道
可以再异常拦截器中,设置response头信息以及响应状态碼,需要注意的是Struts2本身的设计不是一个完全rest的框架,他之所以这样宣称也仅仅是一个嚼头罢了


mht19840918 您好!
俺真是遇到好人了啊,呵呵,多谢你每次都这么耐心帮我答复!
我想可能我需要先把我的需求说清楚一些:
我现在做的rest服务,主要用于客户端形式的网游,其业务数据都由我的rest服务提供。
所以我必须返回xml形式的数据,而不是网页。当然因为rest支持内容协商,strut2 rest plugin也对内容协商这一特性做了较好的支持,可以根据请求后缀的不同返回xml、json或xhtml,这样我觉得假如以后会将一些数据展示在web上,后台服务的重用性就有了保证。

正是出于这一目的,我在做返回值、异常错误等处理的时候,首先希望能够做到用户请求何种类型(xml,json,xhtml),如果有错误,就返回何种类型的表示。
比如xml类型的请求,如果出错,就返回一段xml出错文本,类似:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>NoSuchKey</Code>
  <Message>The resource you requested does not exist</Message>
  <Resource>/mybucket/myfoto.jpg</Resource>
  <RequestId>4442587FB7D0A2F9</RequestId>
</Error>
并附带http错误状态码,比如500。

还有,我还希望,这种处理能够由struts2 rest 框架自动完成。而通过我的试验,我发现这方面框架本身已经做了一定的支持,但支持的程度并不清楚。
比如,在action的validate()中,如果有fielderror,也就是如果返回“input”,并且如果用户请求的是xml类型,struts2 rest 能够自动返回一段xml,这个我试过,是没有问题的。

所以,我就是希望达到这个目的,当出错的时候,能够返回一段xml表示错误信息以及一个错误状态码。成功的时候也一样,一段xml和一个状态码。

如果struts2 rest 框架不能满足这个基本的需求,而需要自定义拦截器去完成的话。那么我有个问题就是,在异常处理的拦截器中,是如何做到内容协商的呢?

我看到你提供的例子:ExceptionInterceptor 中,通过:
if (request.getParameter("ajax") != null)
来判断是否是ajax类型的请求,如果是,则返回json数据类型的错误提示。可是我的应用中,没有提供也不想提供给用户一个标识:ajax,xml,而是想通过访问的后缀:
.xml ,.json, .xhtml 来自动判断。这在自定义拦截器中可以实现么?

//////////

另外,还有一个跟本贴主题无关的几个问题:

new DefaultHttpheaders("xxx"),这里的"xxx"是什么意思,是不是等同于 传统的 result字符串,比如"success","input"?








4 楼 mht19840918 2010-02-27  
可以再异常拦截器中,设置response头信息以及响应状态碼,需要注意的是Struts2本身的设计不是一个完全rest的框架,他之所以这样宣称也仅仅是一个嚼头罢了
3 楼 mht19840918 2010-02-27  
action级别的@Restlt映射:以@Actions组合多个@Action后修饰Action 类,如你的配置。
method级别的result映射:将多个@Result组成数组后作为@Action的Result属性值。

个人的意见如果仅仅是异常的处理,加个异常拦截器就可以。在异常拦截器中指定错误页面就可以。

package com.fost.card.webcommon;

import com.fost.card.CardCustomException;
import com.fost.card.CardRunException;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import net.sf.json.JSONObject;
import org.apache.struts2.ServletActionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* 自定义异常处理拦截器
*
* @author MHT
*
*/
public class ExceptionInterceptor extends AbstractInterceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionInterceptor.class);
    private static final long serialVersionUID = 1L;

    @Override
    public String intercept(ActionInvocation invocation) {

        @SuppressWarnings("all")
        HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().getContext().get(
                ServletActionContext.HTTP_RESPONSE);
        @SuppressWarnings("all")
        HttpServletRequest request = (HttpServletRequest) invocation.getInvocationContext().getContext().get(
                ServletActionContext.HTTP_REQUEST);
        String result = "";
        String op = "";
        Exception excep = null;
        try {
            result = invocation.invoke();
        } catch (CardCustomException e) {
            excep = e;
            result = "error";
            op = e.getMessage();
        } catch (CardRunException ex) {
            excep = ex;
            result = "error";
            op = "对不起, 系统发生错误,请稍后再试";
            LOGGER.error("CardRunException", excep);
        } catch (Exception exx) {
            excep = exx;
            result = "error";
            op = "对不起, 系统发生错误,请稍后再试";
            LOGGER.error("Exception", excep);
        }
        if (excep != null) {
            if (request.getParameter("ajax") != null) {
                response.reset();
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json");
                JSONObject jo = new JSONObject();
                jo.put("op", op);
                try {
                    response.getWriter().print(jo.toString());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
            request.setAttribute("javax.servlet.error.exception", excep);

        }
        return result;
    }

}

result就是你想要指向的异常页面。你甚至可以有多个异常页面。

2 楼 rustlingwind 2010-02-26  
mht19840918 写道
小意思,晚上回去帮你看

谢谢谢谢!全拜托您了!
1 楼 mht19840918 2010-02-26  
小意思,晚上回去帮你看

相关推荐

    噩梦射手 Unity 实训报告

    【噩梦射手项目】"噩梦射手"可能是实训项目的名字,涉及地图生成、角色设定、行走和射击机制、怪物状态机、伤害计算、分数和血量系统等内容,通过这个项目,学生可以全方位地实践Unity游戏开发流程。 【实训总结】...

    快速软件开发-有效控制与完善进度计划-Part1

    进度失控,几乎是每一个软件开发项目挥之不去的噩梦。如何从容赶急,如何通过正确的开发策略和原则,避免典型错误,有效地进行风险管理,从多个方面贯彻执行快速软件开发,都可以从本书中找到答案。本书借助于实际...

    《噩梦射手》的Unity项目文件

    《噩梦射手》是一款基于Unity引擎开发的游戏项目,其源代码和资源文件的提供对于学习和研究Unity游戏开发具有很高的价值。本项目适用于Unity 2019或更高版本,这意味着它利用了Unity引擎的新特性、优化和更新,旨在...

    unity3d打地鼠和噩梦射手游戏完整项目源代码

    同时,“课程设计”意味着它适合教学或自我学习,通过实际操作去理解游戏开发的核心概念和技术。 总结来说,"unity3d打地鼠和噩梦射手游戏完整项目源代码"是一个很好的学习资源,它涵盖了Unity3D的多个重要知识点,...

    噩梦射手官方项目

    U3D官方经典游戏案例噩梦射手,Unity初学者的必选项目。

    Survival Shooter(噩梦射手)成品.rar

    Survival Shooter是unity3d官方发布的一款适合unity游戏开发新手的小游戏,解压文件会有两个unitypackage,自行选择打开哪个。...2.在unity 中 window-&gt;navigation-&gt;All-&gt;bake.可以解决敌人不生成的问题

    Unity噩梦射手资源包.rar

    《Unity噩梦射手资源包》是一个为游戏开发者提供的完整项目资源,特别适合初学者和有经验的开发者用于学习和理解Unity引擎的使用。这个资源包包含了一款名为"噩梦射手"的游戏的所有必要元素,包括场景、角色、动画、...

    年终总结PPT不在是噩梦

    年终总结PPT不在是噩梦

    \年终总结PPT不在是噩梦.ppt

    \年终总结PPT不在是噩梦.ppt \年终总结PPT不在是噩梦.ppt

    庄家的恶梦通达信指标公式源码.doc

    "庄家的恶梦"是一个在通达信平台上的技术指标公式,其设计目的是帮助投资者识别市场中的庄家行为,以及散户、主力的资金动向,从而做出更明智的交易决策。 该指标的主要组成部分包括以下几个关键变量和条件: 1. `...

    年终总结PPT不在是噩梦.pdf

    年终总结PPT不在是噩梦.pdf

    harmonyos2-nightmare-example:噩梦示例

    噩梦示例 设置 git 克隆 $ git clone git@github.com:imunew/nightmare-example.git $ cd nightmare-example 安装 $ npm install 从 config.js.dist 创建 config.js $ cp test/config.js.dist test/config.js $ vi ...

    丧尸有危机 生化危机4重生之恶梦Java版评测.pdf

    丧尸有危机 生化危机4重生之恶梦Java版评测.pdf

    噩梦D涌动.json

    噩梦D涌动.json

    哥谭噩梦1.0PC版(64位).zip

    《哥谭噩梦1.0PC版(64位).zip》是一款基于Unity引擎开发的PC游戏,专为64位操作系统设计。Unity是全球广泛使用的跨平台游戏开发工具,以其强大的图形渲染能力、易用的脚本系统和丰富的资源库而闻名。这款游戏的制作...

    职场噩梦_csdn

    这篇文章主要讲述了职场噩梦的真实案例,揭示了不良的职场环境对员工身心健康造成的严重影响。以下是对文章中提到的知识点的详细说明: 1. 领导风格对员工健康的影响:文章中提到了斯文娅和卡罗琳的案例,说明了...

    command-center:一些用于我日常工作效率的个人工具。 在 PHP 中创建 REST 服务器只是一个挑战

    所以在这里,我面临着一些最糟糕的噩梦。 虽然这个 repo 会随着我更深层次的恐惧和想法而发展,但最后这个 repo 应该包含一个动态网页来跟踪我正在处理的当前任务。 番茄钟计时器、任务列表和一些笔记。 但是功能...

    初中语文文摘历史远去的噩梦

    初中语文文摘历史远去的噩梦

    zhd-e2e-test:zhd e2e与开玩笑和噩梦测试框架

    zhd e2e与开玩笑和噩梦测试框架 建立步骤 # install dependencies npm install # auto run e2e test and auto generate test report npm run docker 测试过程完成后,您可以打开浏览器并键入以查看测试报告。 玩...

Global site tag (gtag.js) - Google Analytics