在第一篇时就说过框架要在URL上作文章,是的,本文就框架怎样充分利用url上作尽可能详细的说明。
做web开发的不可能对url陌生,早在web1.0时代,url作为统一资源定位符,在对web中资源的如何获得上起到巨大作用。不论用户请求的时静态页面或者是各种图片、脚本文件,通过url总能从web网站获取要访问的资源。Web2.0更是常常使用url作为get请求时参数的传递,如http://xxx.xxx.xxx/xxx.jsp?user=admin。以及近几年很火restful web service 摒弃soap而使用url传递请求参数 都说明合理利用url的可行和流行。
当然不止是使用了url就算好的实践,而是能够做到优雅的使用,保证层次分明和整体的简洁,这才算是好的方式,这也正是本框架对使用url 所追求的目标。
首先来看几个例子:
http://www.cnblogs.com/p2
http://www.xxx.com/index.do?page=2
http://www.xxx.com/product/
http://www.xxx.com/channel.do?channel=product
http://www.xxx.com/product/mobile
http://www.xxx.com/channel.do?channel=product&&subChannel=mobile
相信各位看官不用我说也能明白,这几组的实现肯定第一种实现的方式更佳。抛开它能屏蔽服务器端使用的技术这一特性不说,它还能够更好地说明动态网站的层次结构,让用户在访问时能明确知道在网站的什么位置,而不会觉得是陷入了一个迷宫。
当然上面列举的例子是网站前端所使用的url表现方式,因为表现方式可以多种多样,个人喜好不同,本框架在设计时没有给指定前端url的表现方式,而是定义接口,把这个权利留给使用的用户。框架将考虑更多 通用性的东西而不是 个性 自由的东西。
下面对框架里默认使用的url Router AMPPathRouter做详细的介绍,包括设计的思想和实现的方式。首先AMPPathRouter的用途定位为后台使用。为了理解快速的理解它的工作原理,先来和struts做一下对比。
Struts关于请求的配置:
<action name="login" class="com.lscmjx.action.LoginAction" method="login">
<result name="success">
main.jsp
</result>
<result name="failure">
login.jsp
</result>
</action>
它提交的url会是http://xxx.xxx.xxx/login,访问web服务器时会把此url传递到struts框架交给它处理,之后struts会在struts.xml中寻找login的相关的配置,像上面例子,struts会找到LoginAction的类,并且调用其login的方法。
写到这里,我请问这是最好的方式吗?当然不是,至少我在使用struts时就认为这是相当撇脚的设计。上面例子只是列举一个login方法,假如一个系统中要对后台调用的方法是100个,那岂不是就需要在struts.xml中写100个与之类似的配置。想想都头大,这样繁琐的工作,应该是由框架自己去处理,而不是人工给配置。
再来看实现相同功能的Unicorn web框架的配置。
<action class="com.mh.action.UserAction"></action>
当然提交的url肯定需要包含多一些的信息,来保证能通过url正确调用框架Action里的方法。这里提交的url方式:http://xxx.xxx.xxx/UserAction/login/
通过在url里附加调用的Action类的信息,可以省略为不同的方法都在xml里配置的麻烦。假如UserAction里有100个方法,框架也只需这一行的配置。
有了大体的认识之后,来看框架的核心部分AMPPathRouter的具体实现。
/**
* 检查url是否是此Router类要处理的,/Action/Method/Param 格式的将会被检查合格,返回true
* @param relativeUri
* @param actionMap
* @return
*/
public boolean checkUrl(String relativeUri, Map<String, ActionSupport> actionMap) {
Pattern pattern = Pattern.compile("^/\\w+/\\w+/\\S*");
Matcher matcher = pattern.matcher(relativeUri);
if(matcher.matches()) {
String actionName = relativeUri.split("/")[1];
ActionSupport actionSupport = actionMap.get(actionName);
if(null != actionSupport) {
String actionMethodName = relativeUri.split("/")[2];
Class<?> actionClass = actionSupport.getClass();
Method[] methods = actionClass.getMethods();
for(int i = 0; i < methods.length; i++) {
Method method = methods[i];
String methodName = method.getName();
if(methodName.equals(actionMethodName)) {
return true;
}
}
}
}
return false;
}
/**
* 匹配规则为:
* 1、符合/Action/method/param格式,
* 2、并且Action在actionMap中的确存在
* 3、method在此Action中存在
*/
@Override
public boolean route(String relativeUri, UrlFilter urlFilter) {
Map<String, ActionSupport> actionMap = urlFilter.getActionMap();
if(!this.checkUrl(relativeUri, actionMap)) {
return false;
}
// 拦截Action/Method/Param方式的请求,并构建ActionSupport类的属性
String[] params = relativeUri.split("/");
try {
ActionSupport actionSupport = actionMap.get(params[1]);
if(null == actionSupport) {
throw new Exception("找不到" + params[1] + "类");
}
Class<?> action = actionSupport.getClass();
Method method = action.getMethod(params[2], new Class[] {});
if(params.length > 3) {
this.boxingRequest(urlFilter.getRequest(), params[3]);
}
// 只要找到ActionSupport的子类,则初始化其所具有的属性
Object newInstance = action.newInstance();
this.initActionSupport(newInstance, urlFilter);
String result = (String) method.invoke(newInstance, new Object[] {});
if (null == result || ActionSupport.AJAX.equals(result) || ActionSupport.FORWARD.equals(result)) {
return true;
} else {
urlFilter.getResponse().sendRedirect(result);
return true;
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 把url中得param加入到request的attribute里
* @param request
* @param parameter
*/
private void boxingRequest(HttpServletRequest request, String parameter) {
String[] parameters = parameter.split("&");
for (int i = 0; i < parameters.length; i++) {
String param = parameters[i];
String[] key_value = param.split("=");
if(key_value.length == 2) {
request.setAttribute(key_value[0], key_value[1]);
}
}
}
/**
* 初始化ActionSupport类中所需的request、response、session、application等对象
* @param obj
* @param urlFilter
*/
private void initActionSupport(Object obj, UrlFilter urlFilter) {
ActionSupport action = (ActionSupport) obj;
action.setRequest(urlFilter.getRequest());
action.setResponse(urlFilter.getResponse());
action.setSession(urlFilter.getSession());
action.setApplication(urlFilter.getApplication());
}
这便是AMPPathRouter的全部内容,其中在把请求分发到ActionSupport的子类 并调用相关方法时 是通过反射实现,其他地方地方都是相当容易理解的。
空说无凭,把框架应用到实战中才是硬道理:

好了,下一篇介绍Action 和 json。
分享到:
相关推荐
在现代的Web应用程序开发中,RESTful Web Service已经成为构建分布式系统和服务之间通信的重要方式。本文将深入探讨如何利用RESTful架构来实现转账业务,同时关注事务处理和并发控制这两个关键领域。 首先,让我们...
大神的Restful Web Service 详细介绍,Objectives By the end of this class, you should be able to: Give a working definition of RESTful Web Services actions, Enable a RESTful user in the SM operator ...
Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web 源代码Java Restful Web...
使用Java创建RESTful Web Service 在本文中,我们将讨论如何使用Java创建RESTful Web服务。REST(Representational State of Resource)是一种架构风格,它于2000年由Roy Fielding博士提出。RESTful Web服务是一种...
在"RESTful Web Service Demo"项目中,我们将探讨如何使用Java语言来创建这样的服务,并提供CURD(Create、Read、Update、Delete)操作。 首先,理解RESTful架构的关键概念: 1. 资源(Resource):在REST中,一切...
·包含RESTful Web services的真实案例,如Amazon的简单存储服务与Atom发布协议等 ·探讨各种流行编程语言的Web services客户端 ·展示如何用三种流行框架实现RESTful services —— Ruby on Rails、Restlet(基于...
**JAX-RS方式的RESTful Web Service开发详解** RESTful Web Service是一种基于HTTP协议的、无状态的、客户端-服务器交互模式,它利用HTTP方法(GET、POST、PUT、DELETE等)来实现对资源的操作。JAX-RS是Java API ...
标题中的“2018最新谷歌浏览器RESTful Web Service离线版”指的是一个适用于谷歌浏览器的、用于开发和测试RESTful Web服务的工具,该工具的离线版本。RESTful Web Service是一种基于HTTP协议的软件架构风格,用于...
Java RESTful Web Service是现代Web应用开发中的一个重要概念,它基于Representational State Transfer(表述性状态转移)架构原则,提供了一种轻量级、高效且易于理解和实现的接口设计方式。在本PDF教程《Java ...
Restful web service cook book 中文版
Java RESTful Web Service实战是Java开发领域中一个重要的实践教程,它主要涵盖了使用Java技术和RESTful架构风格来创建高效、可扩展的网络服务。REST(Representational State Transfer)是一种网络应用程序的设计...
本教程将通过一个名为"spring-mvc-demo"的项目,详细介绍如何使用Spring框架来实现RESTful Web服务。 一、Spring MVC与RESTful Web服务 Spring MVC是Spring框架的一部分,专门用于处理Web请求和响应。RESTful Web...
编程语言和框架实现:本书讨论了如何使用不同的编程语言和流行的框架(包括Ruby on Rails、Restlet和Django)来实现RESTful Web服务。这意味着开发者可以根据自己的技术栈选择合适的工具来构建符合REST风格的应用。 ...
《Java Restful Web Service实战》源代码.zip是一个包含与Java Restful Web Service开发相关的实践项目源码的压缩包。在本文中,我们将深入探讨Java Restful Web Service的关键概念、技术栈以及如何通过实际示例来...
接下来,我们将使用Java的JAX-RS(Java API for RESTful Web Services)框架来实现RESTful服务。JAX-RS是Java EE的一部分,它提供了一组注解来简化REST服务的开发。 1. **注解基础**: - `@Path`:定义资源路径,...
restful web service cookbook
综上所述,基于RESTful Web Service的数据资源交换系统设计与实现,通过采用RESTful架构、JSON作为数据交换格式,以及Spring Cloud作为微服务框架,可以有效地降低系统开发复杂度,提高系统可扩展性和数据资源管理...
在互联网技术日新月异的今天,Ajax(Asynchronous JavaScript and XML)与Web Service的结合在构建高效、交互性强的网上应用中起着至关重要的作用。本指导学习将深入探讨如何利用这两种技术来重构网上书店,提升用户...
因為剛入職 公司要求會使用struts2 restful風格,剛開始都沒聽說過restful,然後在網上找了N久的講解或demo,都沒找到,花了一週 在老大的指導下搞出來了,希望可以幫助到想學restful風格的同學們