Documentation 文档


关于路径映射 ( @Action / @Namespace )

对于方法调用/映射,最常用的莫过于HTTP请求处理。 比如一个简单的登录方法,返回成功/失败。

                                boolean login(...) {
                                ......
                            

我们希望它能映射到/login或是别的URL路径。
于是,添加 @Action

                                @Action(name = "/login")
                                boolean login(...) {
                                ......
                            

不设置name属性,默认提供方法的名称。

                                @Action
                                boolean login(...) {
                                ......
                            

上面也等同于/login路径。

注意,所有路径都是绝对路径。login会最终补全/,转换为/login。

设置同一类下多个方法路经 @Namespace

                                @Namespace(name = "/user", autoIncluded = true)
                                public class UserAction {

                                    public boolean login(...) {
                                    ......

                                    public Object getUser(...) {
                                    ......
                                }
                            

上面等同于/user/login、/user/getUser 2个路径。
并且,如果设置@Aciton,其优先级大于@Namespace

                                @Namespace(name = "/user", autoIncluded = true)
                                public class UserAction {

                                    @Action(name = "/login")
                                    public boolean login(...) {
                                    ......

                                    public Object getUser(...) {
                                    ......

                                }
                            

上面等同于/login、/user/getUser 2个路径。@Namespace的autoIncluded为true是会检测同一类中public/protected的方法。

当然,可以在方法上设置 @Ignore 忽略映射关系。


关于拦截栈 / 拦截器 ( @InterceptorStack / @Interceptor )

拦截器的作用就是在方法前后左右执行另一些方法。
这里,方法是指@Action映射的方法,另一些方法指拦截器里的方法。

在方法上设置 @Interceptor(name = "...") 表征其是一个拦截器。

                                @Interceptor(name = "timer")
                                public static Object timer(...) {
                                ......

                                @Interceptor(name = "logging")
                                public static Object logging(...) {
                                ......
                            

上面是一个 SampleInterceptor的样列 。这里定义了2个拦截器;其中名为timer拦截器的timer(...)方法记录了方法执行所需的时间,而logging拦截器对应的logging(...)则分别打印执行前后的路径和时间。

注意,拦截器方法中的invocation.invoke()调用不可少,表征拦截器依序调用。

@InterceptorStack 定义多个拦截器组成的拦截栈。拦截栈实质就是一个拦截器数组。这里用注解的形式,更多是为了设置于一个String上方便读取和解析。 见 示例DefaultInterceptorStack

拦截栈 / 拦截器配置

首先,容器会提供一个默认全局拦截栈defaultInterceptorStack属性, 也可能为null

拦截栈 / 拦截器可以配置于类和方法上。

                                @Namespace(interceptors = {"timer", "logging"})
                                public class UserAction {

                                    @Action(interceptorStack = "default", interceptors = {"timer"})
                                    public boolean login(...) {
                                    ......

                                    @Action
                                    public Object getUser(...) {
                                    ......

                                    @Action(interceptorStack = "empty")
                                    public Object getUser2(...) {
                                    ......

                                    @Action(interceptors = {"logging"})
                                    public Object getUser3(...) {
                                    ......
                                }
                            

如上,最终

  • "/login"的拦截器集合 = { "default"[...] + "timer" }
  • "/getUser"的拦截器集合 = { "timer" + "logging" }
  • "/getUser2"的拦截器集合 = { "empty"[...] }
  • "/getUser3"的拦截器集合 = { "logging" }

默认容器的实现:

  • Namespace的拦截器集合 = 存在Namespace指定的拦截栈 ? 指定拦截栈的拦截器集合 + 指定的拦截器集合 : 指定的拦截器集合。
  • Action指定的拦截器集合 = 存在Action指定的拦截栈 ? 指定拦截栈的拦截器集合 + 指定的拦截器集合 : 指定的拦截器集合。
  • Action最终的拦截器集合 = Action指定拦截器集合 > 命名空间拦截器集合 > 全局默认拦截器集合。

注意,拦截器集合是一个有序的可重复的列表。内部实现为ArrayList


关于结果对象 / 结果类型 ( @Result / @ResultType )

方法调用结束会有返回值,结果对象就是指的return值。
结果对象中的type属性对应相应的结果类型,表示同一类类型的结果集。

在方法上设置 @Result(name = "...") 表征其是一个结果对象。
在方法上设置 @ResultType(type = "...") 表征其是一类结果类型。

                                @ResultType(type = "empty")
                                public static void result(...) {
                                ......

                                @ResultType(type = "forward")
                                public static Object actionForward(...) {
                                ......

                                @Result(name = "resultNotFound")
                                public static Object resultNotFound(...) {
                                ......
                            

上面是一个 DefaultResult的样列 。这里定义了2个结果类型和1个结果对象;其中名为empty的类型不对方法的执行结果做任何处理,forward类型于方法执行之后进行转发, resultNotFound则相当于全局处理返回值为"resultNotFound"String类型的方法。

当Result单独定义于方法上时,表示某种特定String类型全局的结果对象。 当Result作为全局结果对象时,type值为空时直接调用后结束;type值不为空调用后再调用相应的ResultType。

结果对象配置

首先,容器会提供一个默认全局结果类型defaultResultType属性, 也可能为null

结果对象@Result 可以配置于方法上,属于@Action的一部分。

                                @Action(results = {
                                    @Result(name = "test", type = "forward", location = "/test/simple2"),
                                    @Result(name = "*")
                                })
                                public String autoRender(...) {
                                ......
                                 
                            

上面是一个在@Action中配置@Result的 SimpleAction的样列。 定义了autoRender(...)方法返回结果的处理方式,返回"test"值会forward值至路径/test/simple2的方法,其它String值会调用一个通配 * 对象类型。

简化,

过多的@Result配置显得繁琐不便。 容器提供了便捷的默认"type : location"表征结果对象的类型和路径。 下面的等同于上面。

                                @Action
                                public String autoRender(...) {
                                    if (...) {
                                    ......
                                        return "forward : /test/simple2";
                                    }
                                    ......
                                    return "*";
                                }
                            

容器默认处理了String返回对象,匹配包括指定@Result、"type : location"值、全局Result等。 如果以上都无匹配,提供了invokeUndefinedResult(...)方法做继承自定义处理(默认不处理直接返回结果字符串)。
对于非String返回对象,容器提供了invokeObjectResult(...)方法做继承自定义处理(默认不处理直接返回对象)。


关于容器

上面多次提及到的容器,实际上即指实现ActionFactory接口默认容器PathActionFactory。 PathActionFactory可被继承,其也提供了诸多protected方法方便复写做自定义的数据处理。

容器初始化属性配置参见jrouter.properties

容器自身配置参见 jrouter.xml。 配置约束参见 jrouter-1.6.xsd

容器默认的配置属性参见 jrouter.properties。 某些配置项跟具体的版本相关。

与springframework的集成。参见 jrouter-spring.xml


关于参数

上述所有例子的参数都是以(...)的形式略过。但实践中,这些参数可以由用户自定义或外界(其它容器)提供。

ActionFactory接口 指明了方法调用的入口invokeAction(String key, Object... params)key是Action的调用路径,参数params是无约束的一个数组。

容器默认提供了MultiParameterConverterFactory 参数转换器,方便做参数类型自动判断和注入。

容器的运行时上下文对象 PathActionInvocation 默认将自身作为参数注入至调用方法的参数中,所以测试用例方法(包括Action、拦截器、结果对象、结果类型)中的 ActionInvocation 参数由此而来。

HTTP servlet项目jrouter-servlet 中提供了支持HTTP参数注入ServletActionFactory