java web怎么写路由_路由设计 · 如何设计一个JavaWeb MVC框架 · 看云

# 路由设计

现代 Web 应用的 URL 十分优雅,易于人们辨识记忆。 路由的表现形式如下:

```

/resources/:resource/actions/:action

http://bladejava.com

http://bladejava.com/docs/modules/route

```

那么我们在java语言中将他定义一个 `Route` 类, 用于封装一个请求的最小单元,

在Mario中我们设计一个路由的对象如下:

```java

/**

* 路由

* @author biezhi

*/

public class Route {

/**

* 路由path

*/

private String path;

/**

* 执行路由的方法

*/

private Method action;

/**

* 路由所在的控制器

*/

private Object controller;

public Route() {

}

public String getPath() {

return path;

}

public void setPath(String path) {

this.path = path;

}

public Method getAction() {

return action;

}

public void setAction(Method action) {

this.action = action;

}

public Object getController() {

return controller;

}

public void setController(Object controller) {

this.controller = controller;

}

}

```

所有的请求在程序中是一个路由,匹配在 `path` 上,执行靠 `action`,处于 `controller` 中。

Mario使用一个Filter接收所有请求,因为从Filter过来的请求有无数,如何知道哪一个请求对应哪一个路由呢?

这时候需要设计一个路由匹配器去查找路由处理我们配置的请求,

有了路由匹配器还不够,这么多的路由我们如何管理呢?再来一个路由管理器吧,下面就创建路由匹配器和管理器2个类:

```java

/**

* 路由管理器,存放所有路由的

* @author biezhi

*/

public class Routers {

private static final Logger LOGGER = Logger.getLogger(Routers.class.getName());

private List routes = new ArrayList();

public Routers() {

}

public void addRoute(List routes){

routes.addAll(routes);

}

public void addRoute(Route route){

routes.add(route);

}

public void removeRoute(Route route){

routes.remove(route);

}

public void addRoute(String path, Method action, Object controller){

Route route = new Route();

route.setPath(path);

route.setAction(action);

route.setController(controller);

routes.add(route);

LOGGER.info("Add Route:[" + path + "]");

}

public List getRoutes() {

return routes;

}

public void setRoutes(List routes) {

this.routes = routes;

}

}

```

这里的代码很简单,这个管理器里用List存储所有路由,公有的 `addRoute` 方法是给外部调用的。

```java

/**

* 路由匹配器,用于匹配路由

* @author biezhi

*/

public class RouteMatcher {

private List routes;

public RouteMatcher(List routes) {

this.routes = routes;

}

public void setRoutes(List routes) {

this.routes = routes;

}

/**

* 根据path查找路由

* @param path请求地址

* @return返回查询到的路由

*/

public Route findRoute(String path) {

String cleanPath = parsePath(path);

List matchRoutes = new ArrayList();

for (Route route : this.routes) {

if (matchesPath(route.getPath(), cleanPath)) {

matchRoutes.add(route);

}

}

// 优先匹配原则

giveMatch(path, matchRoutes);

return matchRoutes.size() > 0 ? matchRoutes.get(0) : null;

}

private void giveMatch(final String uri, List routes) {

Collections.sort(routes, new Comparator() {

@Override

public int compare(Route o1, Route o2) {

if (o2.getPath().equals(uri)) {

return o2.getPath().indexOf(uri);

}

return -1;

}

});

}

private boolean matchesPath(String routePath, String pathToMatch) {

routePath = routePath.replaceAll(PathUtil.VAR_REGEXP, PathUtil.VAR_REPLACE);

return pathToMatch.matches("(?i)" + routePath);

}

private String parsePath(String path) {

path = PathUtil.fixPath(path);

try {

URI uri = new URI(path);

return uri.getPath();

} catch (URISyntaxException e) {

return null;

}

}

}

```

路由匹配器使用了正则去遍历路由列表,匹配合适的路由。当然我不认为这是最好的方法,

因为路由的量很大之后遍历的效率会降低,但这样是可以实现的,如果你有更好的方法可以告诉我 :)

在下一章节我们需要对请求处理做设计了~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值