struts2-freeroute-plugin 
自由的映射路由,像 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
通过
Results
和Result
等 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
}