Mapping route like Spring MVC
Java
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
struts2-freeroute-core
struts2-freeroute-example
struts2-freeroute-plugin
struts2-freeroute4spring
.gitignore
.travis.yml
LICENCES
NOTICES
README.md
pom.xml

README.md

struts2-freeroute-plugin Build Status

自由的映射路由,像 Spring MVC 那样。

引用

当前最新版本 1.0.4

<dependency>
    <groupId>com.bastengao.freeroute</groupId>
    <artifactId>struts2-freeroute-plugin</artifactId>
    <version>1.0.4</version>
</dependency>

如果你需要与 struts2-spring-plugin 结合使用,只需要以下依赖

<dependency>
    <groupId>com.bastengao.freeroute</groupId>
    <artifactId>struts2-freeroute4spring</artifactId>
    <version>1.0.4</version>
</dependency>

例子

struts.xml

<struts>
    <constant name="struts.freeroute.controllerPackage" value="org.example"/>
</struts>

org.example.BookController.java

public class BookController{
    private int id;
    private Book book;

    @Route("/books/{id}")
    public String show(){
        book = bookDao.find(id);
        return Results.jsp("/book.jsp");
    }

    //setter, getter
}

webapp/book.jsp

<!DOCTYPE html>
<html>
    <head>
        <title>show book</title>
    </head>
    <body>
        <h1>Hello book</h1>
    </body>
</html>

访问 "/books/13", 则会显示 book.jsp 的内容

配置

属性 可选 描述 默认
struts.freeroute.controllerPackage 必须 配置 Controller 所在的包, 插件会在此包下查找相应的 Controller,包括子包
struts.freeroute.controllerSuffixes 可选 配置 Controller 的后缀。只解析 controllerPackage 下所有以 Controller 结尾的类。 可指定多个后缀,中间用逗号隔开 Controller
struts.freeroute.defaultParentPackage 可选 配置默认的父包 struts-defualt
struts.freeroute.contentBase 可选 配置全局的内容基路径,类似于 @ContentBase。 如果返回结果中路径是相对地址,则通过内容基路径将其转换为绝对路径。 如果 controller 类上有 @ContentBase 注解则优先使用。

struts.xml

<struts>
    <constant name="struts.freeroute.controllerPackage" value="org.example"/>
    <!-- 将默认 Controller 改为 Action 和 Controller -->
    <constant name="struts.freeroute.controllerSuffixes" value="Action, Controller"/>
    <constant name="struts.freeroute.contentBase" value="/pages/content"/>
    <constant name="struts.freeroute.defaultParentPackage" value="my-struts"/>

    <package name="my-struts" extends="struts-default">
    </package>
</struts>

说明

配置struts.freeroute.controllerPackage后, 会在此包中默认搜索以Controller结尾的类做为 Controller, 并在其中查找所有@Route 注解的方法做为路由映射.

路由映射

Controller任意方法上加@Route注解则表示一条路由.

例如:

public class MyController{
    @Route("/helloworld")
    public String hello(){
        return Results.html("/world.html)";
    }
}

路径

  • 简单路径映射

/helloworld => http://HOST:PORT/helloworld

@Route("/helloworld")
  • 路径中包含变量(pathVariable)

变量可以是英文,数字,中文和 - _ ~ . 这四个标点符号(其他标点符号都不支持,参考List_of_allowed_URL_characters)。

/users/{id} => http://HOST:PORT/users/1013

// id将会赋予{id}变量值
private int id;

@Route("/users/{id}")
public String user(){
    //...
}

// setter, getter

/users/{id}/tags/{name} => http://HOST:PORT/users/1013/tags/free

// {id}
private int id;
// {name}
private String name

@Route("/users/{id}/tags/{name}")
public String tagedUser(){
    //...
}

// setter, getter

注意:路径变量比参数的优先级高, 上面的例子中请求如果是 http://HOST:PORT/users/1013/tags/free?name=never , controller 中的 name 属性值将会是 free 而不是 never

  • 路由嵌套

在 controller 类中加 @Route 注解起到路径嵌套的作用,其中只有 value 属性有效

@Route("/users")
public class UserController {

    // GET "/users"
    @Route(method = MethodType.GET)
    public String index(){
        //...
    }

    // GET "/users/{id}"
    @Route(values = "/{id}", method = MethodType.GET)
    public String show(){
        //...
    }
}

绑定 cookie

通过在属性上加 @CookieValue 注解绑定某个 cookie 的值

//如果有 name 为 id 的 cookie 存在,那么将会把 cookie 的值绑定给 userId 属性
@CookieValue("id")
private String userId;

@Route("/users")
public String show(){
    //...
}

// setter, getter

HTTP method

通过@Route.method指定 HTTP method, 匹配满足 HTTP method 的路由映射

method 目前有以下类型:

  • DELETE
  • GET
  • HEAD
  • OPTIONS
  • POST
  • PUT
  • TRACE

@Route.method默认表示匹配任意一种 HTTP method.

只响应 POST 请求, POST http://HOST:PORT/users

@Route(value = "/users", method = MethodType.POST)

或者只响应 GET 和 POST 请求, GET|POST http://HOST:PORT/users

@Route(value = "/users", method = {MethodType.GET, MethodType.POST})

HTTP 参数

通过@Route.params指定 HTTP param , 匹配满足 HTTP param 的路由映射

只响应带 'order' 参数的请求, GET http://HOST:PORT/users?order=time

@Route(value = "/users", params = {"order"})

可以有多个参数, GET http://HOST:PORT/users?order=time&page=13

@Route(value = "/users", params = {"order", "page"})

参数存在且等于某个值, GET http://HOST:PROT/users?name=basten

@Rotue(value = "/users", params = {"name=basten"})

参数存在但不等于某个值, GET http://HOST:PROT/users?name=basten 将会产生 404,如果 name 是其他值则不会

@Rotue(value = "/users", params = {"name!=basten"})

拦截器

通过 @Route.interceptors 指定拦截器,可以指定多个,顺序为由左到右。

struts.xml

<package name="myPackage" extends="struts-default">
    <interceptors>
        <interceptor name="myInterceptor" class="org.example.action.MyInterceptor"/>

        <interceptor-stack name="myStack">
            <interceptor-ref name="defaultStack"/>
            <interceptor-ref name="myInterceptor"/>
        </interceptor-stack>
    </interceptors>
</package>
@ControllerPackage(parent = "myPackage")
public class MyController {

    @Route(value = "/path", interceptors = "myStack")
    public String view(){
        //...
    }
}

返回结果

Controller.routeMethod 方法的返回值将决定返回的结果类型和页面路径, 如dispatcher:/example.html, 类型为 dispatcher, 页面路径为 /example.html.

两种方式:

  • 字面值

    例如 dispatcher:/example.html,这种方式只要返回 type:location 或者直接返回 type

  • DSL

    通过 ResultsResult 等 DSL 方式的 api 构造返回结果。Results 能够满足常用返回结果。例如:

    • Results.html("/example.html") 或者 Results.html("/example") 后缀自动补全(包括 html, jsp, freemarker(ftl), velocity(vm))
    • Results.jsp("/exmaple.jsp")
    • Results.json().includeProperties("value1, value2").done()

    不过有时候 Results 未覆盖的情况,也可以通过 Result 来组织返回结果。例如:

    Result.create("json")
        .param("includeProperties", "value1, value2")
        .done();

目前支持以下类型:

  • dispatcher
    • html
    • jsp
  • redirect
  • chain
  • httpHeader
  • stream
  • velocity
  • freemarker
  • json

绝对路径

页面路径以 "/" 开始

@Route("/very-long-page-path")
public String show(){
    return Results.html("/very/long/page/path/example.html");
}

@Route("/anothor-very-long-page-path")
public String show2(){
    return Results.html("/very/long/page/path/example2.html");
}

相对路径

页面路径不是以 "/" 开始,其地址相对于 @ContentBase 的路径

@ContentBase("/very/long/page/path")
public class ExampleController{
    @Route("/very-long-page-path")
    public String show(){
        return Results.html("example.html");
    }

    @Route("/anothor-very-long-page-path")
    public String show2(){
        return Results.html("example2.html");
    }
}

包配置

我们可以通过全局配置 struts.freeroute.defaultParentPackage 来设置默认父包, 我们了可以通过 ControllerPackage 来自定义每个 Controller 的父包, 类似于 struts 的 package 中的 extends

struts.xml

<package name="myPackage" extends="struts-default">
    <!-- interceptors, actions -->
</package>
@ControllerPackage(parent = "myPackage")
public class MyController {
    // do something
}