Action Result 是action方法的一个返回值。返回的对象提供一个string结果,也就是这个对象的toString()的值。返回的String的格式如下:
result string = <result_type>:<result_value>
返回类型决定了madvoc选择哪个“结果处理器”来处理返回的结果。 返回值是用来创建相应路径。
返回值的类型又如下:
result path = <action_path_no_ext>.<result_value>
action也可以返回void,这会触发返回值类型处理器处理一个空的结果,返回null也是一样的效果。
当返回值以“/”符号开始的时候,madvoc会认为这是一个完整的响应路径,所以,返回的值也就是响应的路径。
Servlet分发是默认的返回结果类型,这个结果处理器加上扩展名“jsp”来创建页面的名字和路径。如果这个页面没有找到,分发器(dispatcher)会从后边开始删除一个单纯,然后继续寻找,以此类推,知道找到页面。
以下是一个hello world的例子:
@MadvocAction public class HelloAction { @Action public String world() { return "ok"; } }
这个action映射的路径是:/hello.world.html,现在这个结果,有一个明确的假定结果类型:dispatch。返回的结果是ok,madvoc会根据ok去寻找页面,寻找顺序如下:
分发器(dispatcher)会依次去寻找以上的页面,如果都没有找到,则返回404错误。
Servlet 重定向很简单:返回值 指定 重定向URL,一般情况下,返回值以全路径(“/”开头)重定向URL:
@MadvocAction public class HelloAction { @Action public String world() { return "redirect:/index.html"; } }
URL重定向可以包含所有必需的参数在里面,说到这个,jodd提供了一个小巧的工具创建url和编码url参数。
此外,也可以注入action的属性到url的参数里面去:
@MadvocAction public class OneAction { String value; @Action public String execute() { value = "173"; return "redirect:/index.html?value=${value}"; } }
以上的代码,如果请求路径:/one.html 则会跳转到/index.html?value=173 去。
结果链(chain result)和转发类似,只不过结果链是在madvoc内部完成,二转发是在servlet容器里面完成。这里我们可以理解为结果链就是转发。结果链类型处理器会使用返回的结果当做下一个action的路径,约束下一个action执行在第一个action之后(包括所有的拦截器)。以下例子说明这个类型结果:
@MadvocAction public class HelloAction { @Action public String chain() { return "chain:/hello.link.html"; } @Action public void link() { } }
第一个action会映射到;/hello.chain.html。当第一个action执行完毕之后,madvoc会继续执行第二个action,也就是: /hello.link.html。当发送的action被执行,它的执行和外面直接请求过来的结果是一样的,这两者没有什么不同。
第一个action可以使用request,session等各种不同的作用域来给第二个action发送自己的逻辑数据。
URL重定向的主要问题是 如果传参的话必须通过url的get请求的方式传参,这就需要完全的,准确的把我们要传的参数拼接成url格式。虽然jodd有很多很好的工具来帮助我们打到这个需求,但是这并不是最好的,可维护性高的,可视化的,优雅的解决方案。
移动结果类型处理器 除了它在重定向之前存储当前的action到session之外 和 重定向相似。重定向之后,madvoc发现被存储的action,然后把action数据注入到request属性中。因为这样,所有来之action的数据相对目标action来说都变成了可视化的数据。这样,我们就从硬编码到url参数中解放出来了。
要理解“moving”移动action最好的方法是和上面的redirect分发做个比较。这个目标的action非常简单,而且有一个value输入(属性value注解上@In):
// Target action @MadvocAction public class TwoAction { @In String value; @Action(alias = "two") public void view() { System.out.println(value); } }
现在,请求这个action,这个例子会显示这个action的两个版本:一个是使用“redirect”的结果,另一个是使用“move”的结果:
// Version #1: action that uses redirection to target @MadvocAction public class OneAction { String value; @Action public String execute() { value = "173"; return "redirect:/<two>?value=${value}"; } }
// Version #2: action that uses moving to target @MadvocAction public class OneAction { @Out String value; @Action public String execute() { value = "173"; return "move:/<two>"; } }
这两个action作用完全一样,但不同的地方也非常明显:第二个action值为结果准备了数据而没有对url进行改变。
有一些 当数据需要直接当做流的形式作为HTTP响应 情况,因为这样,action方法为负责发送完整的响应,action也可以返回“none:”,这个返回类型不会执行任何额外的结果处理代码。因此,action负责发送返回结果数据。这个结果类型处理器不会带走任何的结果数据,结果数据是被忽略的。
当action与直接响应一起工作的时候,action需要直接的请求到http的请求(request)和响应(response),虽然他们能简单的注入到action类实例对象中去,这样,类与servlet接口就变成了“硬链接”:它不能容易的在外边的容器被初始化。
这个结果处理器的目的是分开这个处理为两部分:准备数据和真实数据传递。这样达到离开HTTP servlet的“干净”的action类的目的。
发送一些二进制数据作为输出的例子是很常见的,比如显示图片和文件下载。虽然使用“none:”类型处理器可以直接的发送二进制内容,但是在实际中,这是没有进过慎重考虑的。
现在,madvoc提供了两个方法来打到我们的需求,第一个很明显,就是使用action方法来准备二进制数据,然后把这个数据保存起来,结果类型处理器把这些数据返回给客户端。以下是一个自定义类型和访问二进制的例子:
@MadvocAction public class RawAction { byte[] bytes; @Action public RawResultData view() { bytes = ... // create byte array somehow return "foo:bytes"; } }
这里,一些结果类型处理器(例子中是foo)使用反射和读取所有属性字段的方式来标示数据(例子中的是byte)和返回数据 的方式来处理action的对象。当然,这仅仅是一种方案。还有很多方法来处理这个情况,比如使用注解来代替返回值等。
madvoc提供了另一个更方便的处理方式来代替这种返回一个字符串的方式。action可以返回任何类型对象,这个要看 结果类型处理器 如何来处理返回的结果值,结果路径 和结果对象。到目前为此,所有的结果类型处理器都只是用了结果值(object的toString())和结果路径。但是结果类型处理器可以进一步来返回整个object对象。去理解这个最好的办法是是用以下的方法来重构上面的例子。
@MadvocAction public class RawAction { @Action public RawResultData view() { byte[] bytes = ... // create byte array somehow return new RawResultData(bytes); } }
RawResultData 只是一个对二进制数据的简单封装 来把 二进制数据返回给客户端。它是和二进制数据类型处理器一起工作的。RawResultData 已经重写了toString() 方法 返回 “raw:”,所有的action方法要做的就是准备byte数据,然后以RawResultData返回。
以下的表格是对的ResultMapper 总结。