目录[-]
规则配置
管理器
URL重写处理
代码行统计
总结
RESTful方式的访问确实即方便又易用,确实是非常不错的一种架构模式。前面一直嘴馋了好长时间,但是由于时间及人员关系,一直没有启动,刚开年,时间也有了,人员也到位了,没啥说的,开工!
本人的习惯,在开工之前,先去学习、研究、了解别人是怎么做的,在看了大量的文档及Roy Thomas Fielding博士的论文还有大量的实践之后,对于它是个啥,解决了啥等等有了比较充分的认识,接现来就是实现了。
程序员同学的第一想法是采用Spring中的RESTful方案来进行解决,这个当然马上被我否掉,原因是这个会导致对SpringMVC的依赖,第二会导致所有的实现都和RESTful进行硬绑定,如果有一天,出来另外一种XXXful的支持,程序员们必须要通过修改代码才能实现,这个与本人提倡的一次开发到处使用有冲突,而且会让程序员知道RESTful相关的实现细节,这明显会增加程序员的学习与开发成本。如果要修改Restful的访问方式,还要去修改相关源码,这个也太恶了,难以忍受。
那程序员同学的问题就来了,你说怎么做?
佛家对看事物有三个层次,第一层是看山是山 看水是水,第二层是看山不是山,看水不是水,第三层次是看山还是那山,看水还是那水。
所以对于RESTful这个东东,也是同样的问题,如果套用上面的3个层次来分析的话,大概是这样的:
第一层次:看山是山 看水是水,看到RESTful就是RESTful,于是就直接针对这个做了。当然这个层次比较低,我前面说的程序员同学就是这个思路,缺点上面我都已经上过了。
第二个层次:看山不是山,看水不是水,看到RESTful的时候,隐隐约约看着,它根本就不是啥新东西,它就是我们常用的WEB访问的一种新的约定和规范,再说得直接一点,它就是一种门面,对原来的访问方式进行了一种新的组织而已。
第三个层次:看山还是那山,看水还是那水,这个时候再看RESTful,就知道它的实质了,它根本就不是个啥,它就是定义了一套新的访问规范而已。
它通过HTTP方法来声明访问方式,它通过ACCEPT来声明返回数据格式,它通过多层的URL路径来传一些参数。
它和具体的代码与控制层实现逻辑有1毛钱关系么??从本来来说是没有的。因此,通过上面的抽象,我们可以认为,RESTful架构实际上可以认为就是一系列的URL地址的进行转换规则,它通过预定义好的规则,把RESTful格式的请求转换成我们原来的已经开发好的一些访问地址就可以了,其它的就该咋咋地好了。
通过上面的讲解,程序员同学似乎懂了我说的意思,于是去噼里啪啦敲代码了,半天以后,代码出来了,大致如下:
规则配置
转换规则定义:
<rules> <rule pattern="/users/{id}"> <mapping method="get" accept="text/html" url="queryUsersTiny.servicepage"></mapping> <mapping method="post" accept="text/html" url="addUserTiny.servicepage"></mapping> <mapping method="put" accept="text/html" url="updateUserTiny.servicepage"></mapping> <mapping method="delete" accept="text/html" url="deleteUserTiny.servicepage"></mapping> <mapping method="get" accept="text/json" url="queryUsersTiny.servicejson"></mapping> </rule> <rule pattern="/users/new/"> <mapping method="get" accept="text/html" url="crud/restful/operate.page"></mapping> </rule> <rule pattern="/users/edit/{id}"> <mapping method="get" accept="text/html" url="queryUserByIdTiny.servicepage"></mapping> </rule> <rule pattern="/users/{id}/classes/{name}"> <mapping method="post" accept="text/html" url="queryclasses.servicepage"></mapping> </rule> </rules> <div> </div>
说明:
rules下面放置一系列的url转换规则rule。
rule表示一条转换规则
pattern:属性是一条匹配表达式,表示这种类型的URL地址是归我处理的,它下面可以有占位符,来表示要提取一些值
在它下面呢,有多条的mapping 子规则,mapping 中有如下属性:
method:响应的请求方法
accept:响应的返回类型
url:真正执行的URL
管理器
管理器就是个规则仓库,里面放置了所有的规则。
public interface UrlRestfulManager { String URL_RESTFUL_XSTREAM ="urlrestful"; /** * 增加restful配置信息 * @param Rules */ public void addRules(Rules Rules); /** * 移除restful配置信息 * @param Rules */ public void removeRules(Rules Rules); /** * 根据请求路径、请求的方法以及请求头的accept 组装此次请求的上下文对象 * @param requestPath * @param httpMethod * @param accept * @return */ public Context getContext(String requestPath, String httpMethod, String accept); }
public class UrlRestfulFileProcessor extends AbstractFileProcessor { private static final String RESTFUL_EXT_FILENAME = ".restful.xml"; private UrlRestfulManager urlRestfulManager; public boolean isMatch(FileObject fileObject) { return fileObject.getFileName().toLowerCase() .endsWith(RESTFUL_EXT_FILENAME); } public void setUrlRestfulManager(UrlRestfulManager urlRestfulManager) { this.urlRestfulManager = urlRestfulManager; } public void process() { XStream stream = XStreamFactory .getXStream(UrlRestfulManager.URL_RESTFUL_XSTREAM); for (FileObject fileObject : deleteList) { logger.logMessage(LogLevel.INFO, "正在移除restful文件[{0}]", fileObject.getAbsolutePath()); Rules Rules = (Rules) caches.get(fileObject .getAbsolutePath()); if (Rules != null) { urlRestfulManager.removeRules(Rules); caches.remove(fileObject.getAbsolutePath()); } logger.logMessage(LogLevel.INFO, "移除restful文件[{0}]结束", fileObject.getAbsolutePath()); } for (FileObject fileObject : changeList) { logger.logMessage(LogLevel.INFO, "正在加载restful文件[{0}]", fileObject.getAbsolutePath()); Rules Rules = (Rules) stream.fromXML(fileObject .getInputStream()); Rules oldRules = (Rules) caches.get(fileObject .getAbsolutePath()); if (oldRules != null) { urlRestfulManager.removeRules(oldRules); } urlRestfulManager.addRules(Rules); caches.put(fileObject.getAbsolutePath(), Rules); logger.logMessage(LogLevel.INFO, "加载restful文件[{0}]结束", fileObject.getAbsolutePath()); } } }
这个类用于匹配所有的RESTful规则文件并添加到管理器。
这样就可以进行良好的模块化,把各模块中的配置文件统一加载起来,统一使用。易于开发,自动集成。
URL重写处理
public class RestfulStyleSubstitutionHandler implements RewriteSubstitutionHandler { private static final String Accept = "Accept"; private static final String HTTP_METHOD_KEY = "X-HTTP-METHOD-OVERRIDE"; private UrlRestfulManager urlRestfulManager; public void setUrlRestfulManager(UrlRestfulManager urlRestfulManager) { this.urlRestfulManager = urlRestfulManager; } /** * 先获取原来的请求路径与UrlRestful的配置进行匹配,把匹配的值放到上下文中,最后重新设置请求的路径。 */ public void postSubstitution(RewriteSubstitutionContext context) { String originalPath = context.getPath(); String httpMethod = getHttpMethod(context); String requestAccept = context.getParserWebContext().get(Accept); Context restfulContext = urlRestfulManager .getContext(originalPath, httpMethod, requestAccept); if (restfulContext != null) { ParameterParser parameterParser = context.getParameters(); setParameter(parameterParser, restfulContext.getVariableMap()); context.setPath(restfulContext.getMappingUrl()); } } private String getHttpMethod(RewriteSubstitutionContext context) { WebContext webContext = context.getParserWebContext(); String httpMethod = webContext.get(HTTP_METHOD_KEY); if (StringUtil.isBlank(httpMethod)) { httpMethod = webContext.getRequest().getMethod(); } return httpMethod; } private void setParameter(ParameterParser parameterParser, Map<String, String> variableMap) { if (!CollectionUtil.isEmpty(variableMap)) { for (String key : variableMap.keySet()) { String value = variableMap.get(key); if (!StringUtil.isBlank(value)) { String[] parameterValues = value.split(","); if (parameterValues.length > 1) { parameterParser.setObjects(key, parameterValues); } else { parameterParser.setObject(key, value); } } } } } }
这里的逻辑很简单,得到访问路径然后到管理器中查找看是否有对应的,如果有则进行rewrite处理。
这里有个处理逻辑是:X-HTTP-METHOD-OVERRIDE参数,这个参数可以通过放在HEADER、REQUEST等地方来声明请求类型,如果这个值有,则采用声明的方法,否则用HTTP请求的方法来进行处理,这就允许通过一个POST方法来处理所有的请求方式。推荐采用放在HEADER来进行声明的。
代码行统计
连接口带配置带实现,总结代码行数480行(ValueParser现在还未使用)。
总结
自此,已经完成了对Tiny框架的扩展,支持了RESTful访问方式完美支持,至于如何定义访问格式及路径层次结构规划,那是技术经理和开发人员的事情。对于已经使用Tiny框架的项目,只要增加新的依赖,然后增加配置就可以对外提供RESTful的访问支持了。
对于非Tiny项目,也可以采用上面的开发思路,来做自己的RESTful风格访问支持。
功能特点:对原有实现无任何侵入性(重定向地址要转向RESTful格式的新地址)。
上面的分析及解决方案如有不对或不妥之处,欢迎批评指正。
欢迎登录关注:http://bbs.tinygroup.org,本例涉及的代码和框架资料,将会在论坛分享。技术交流群:228977971,让我们一起动手,了解框架的奥秘!
相关推荐
本项目就是一个用Delphi实现的HTTP服务器,它特别强调了对RESTful风格路由的支持。 REST(Representational State Transfer)是一种软件架构风格,用于设计网络应用程序,尤其适用于Web服务。其核心思想是通过HTTP...
在SpringMVC中实现RESTful风格,可以创建更加灵活、易于理解和维护的API。让我们深入探讨一下SpringMVC如何实现RESTful风格以及相关知识点。 首先,理解RESTful的基本原则至关重要。REST(Representational State ...
本文将深入探讨如何在Spring MVC中实现RESTful风格的CRUD操作,这对初学者尤其有价值。 首先,了解REST(Representational State Transfer,表述性状态转移)是一种网络应用程序的设计风格和开发方式,基于HTTP协议...
3. **Spring MVC与RESTful**:Spring Boot默认使用Spring MVC作为其Web框架,Spring MVC提供了对RESTful风格的支持。通过`@RestController`注解,我们可以将控制器类标记为处理HTTP请求,返回JSON或XML等资源。`@...
本篇文章将探讨在Java领域中,如何使用Apache CXF框架实现RESTful风格的Web服务开发。** **1. RESTful风格的基本概念** RESTful风格的核心理念是将网络上的各种资源抽象为URI(统一资源标识符),并通过HTTP方法...
### RESTful URL最佳实践 #### 一、REST简介与HTTP方法映射 REST(Representational State Transfer)是一种软件架构风格,由Roy Thomas Fielding在2000年提出,主要应用于Web Services的设计与实现。REST将Web视...
Apache CXF不仅支持传统的SOAP Web服务,也支持RESTful风格的服务。使用CXF开发RESTful服务,我们可以利用JAX-RS(Java API for RESTful Web Services)规范,它是Java平台上的RESTful服务开发标准。 **三、CXF与...
Spring MVC是Spring框架的一部分,它允许开发者用Java配置和注解来创建Web应用程序,支持RESTful风格的API设计。整合FastJson的目的是为了在处理HTTP请求和响应时能快速、高效地序列化和反序列化JSON数据。 1. **...
### SpringBoot RESTful API 架构风格实践 #### 1. RESTful API 概述 ##### 1.1 什么是 RESTful API REST (Representational State Transfer) 是一种软件架构风格,它定义了一系列规则和约束条件,用于构建分布式...
【标题】:“用CXF开发RESTful风格WebService” 在Web服务的世界中,REST(Representational State Transfer,表现层状态转移)已经成为一种广泛采用的架构风格,它强调资源的表示和通过HTTP方法进行操作。CXF,...
在IT行业中,构建RESTful风格的服务端应用是现代Web开发的主流趋势,它强调资源的表述性和统一的接口。Spring Boot结合Spring Security框架为开发者提供了一种高效且安全的方式来实现这一目标。这篇博客将深入探讨...
本项目“基于tp5的restfulapi风格接口oauth20接口版本管理”旨在利用ThinkPHP5框架实现一个支持OAuth2.0授权协议的RESTful API,提供接口版本管理功能,这在现代Web服务和移动应用开发中至关重要。 首先,让我们...
在本示例中,我们将深入探讨如何使用Spring MVC实现RESTful风格的API,以完成增删改查(CRUD)操作。 RESTful是一种Web服务设计风格,全称为Representational State Transfer(表现层状态转移)。它的核心思想是...
总结来说,这个基于Tornado和RESTful风格的Python后台管理系统展现了现代Web开发的趋势和最佳实践。通过使用Tornado框架,开发者可以构建出高并发、响应迅速的后台服务,而RESTful API设计则确保了接口的清晰性和可...
Restful.NET是一个基于.NET框架实现RESTful架构风格的Web服务开发工具。REST(Representational State ...在实践中,还需要关注性能优化、API设计的最佳实践以及持续集成和部署等方面,以打造高质量的RESTful服务。
在构建Web服务时,Spring框架提供了强大的支持,特别是在创建RESTful API方面。REST(Representational State Transfer)是一种架构风格,用于构建简洁、可扩展的网络应用程序。本篇文章将深入探讨如何利用Spring...
Java 使用 Feign 实现声明式 Restful 风格调用是当前流行的微服务架构中的一种常见实践。Feign 是 Netflix 开发的声明式、模板化的 HTTP 客户端,可以帮助我们更加优雅的调用服务提供者的 API。在本文中,我们将详细...
RESTful风格使得API更加简洁,易于理解和使用。 这个学习案例应该是教你如何在Eclipse环境下,利用Spring Boot作为基础框架,集成Dubbo服务治理框架,使用Zookeeper进行服务注册和发现,MyBatis作为数据访问层,...
RESTful图书管理系统是一种基于REST(Representational State Transfer)架构风格的图书管理系统。它利用HTTP协议的各种方法来实现对图书数据的增删改查等功能,旨在通过标准化的方式提高系统的可维护性、扩展性和互...