`
j2eetop
  • 浏览: 60247 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

RESTful风格的支持实践

 
阅读更多

目录[-]
规则配置
管理器
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,让我们一起动手,了解框架的奥秘!

分享到:
评论

相关推荐

    RESTfulHTTP的实践

    探讨了开发者在设计RESTfulHTTP应用时所面临的典型问题,展示了如何在实践中应用REST架构风格,描述了常用的URI命名方法,讨论了如何使用统一接口进行资源交互,何时使用PUT或POST以及如何支持非CURD操作等。...

    Hasor开发框架 v3.2.2

    Hasor开发框架是一款基于Java语言的应用程序开发框架,它的核心设计目标...方便进行业务深度解耦,使业务逻辑更佳清晰10、支持Web类型项目开发,提供restful风格的mvc开发方式11、支持Form表单验证、支持场景化验证12、

    安卓快速开发框架AndroidOne.zip

    One框架能帮您带来什么?... 改造实现SyncHttpClient,支持同步,并支持RESTFUL风格,调接口时可直接单元测试 实现参考类 SyncHttpClient.java 标签:AndroidOne

    JAVA毕业设计之springboot112基于Spring Boot技术的卓越导师双选系统设计与实现源代码.zip

    RESTful API:项目提供了一套RESTful风格的API接口,方便前端与后端进行数据交互。这些接口遵循HTTP协议的标准,易于理解和使用。安全性:项目采用了常见的安全措施,如用户认证和授权,以确保只有合法用户才能访问...

    Hasor开发框架

    10、支持Web类型项目开发,提供restful风格的mvc开发方式 11、支持Form表单验证、支持场景化验证 12、提供开放的模版渲染接口,支持各种类型的模版引擎 13、提供丰富的工具箱,帮助您快速开发,有了它您甚至不需要 ...

    Hasor开发框架-其他

    10、支持Web类型项目开发,提供restful风格的mvc开发方式 11、支持Form表单验证、支持场景化验证 12、提供开放的模版渲染接口,支持各种类型的模版引擎 13、提供丰富的工具箱,帮助您快速开发,有了它您甚至不需要 ...

    基于微信小程序的学生知识成果展示与交流的实现+ssm框架.rar

    使用Spring MVC进行前后端数据交互,采用RESTful风格的API设计,提高系统的灵活性和可扩展性。 结合MyBatis框架进行数据持久化操作,管理帖子信息、用户信息、评论信息等,确保数据安全和一致性。 知识成果展示: ...

    RapidWebDev框架源码

    实践证明,它可以让项目节省超过50%的代码,并且代码质量和开发效率比其他的解决方案都要高出很多 设置Xml Schema 复制如下XML定义文件(C:\MyProject\RapidWebDev\xml schema\目录下找到它们)到你vs2008的Schemas...

    OAuth协议 介绍

    OAuth构建于已被多个站点独立实现的已有协议和最佳化实践之上,是一个被大小服务提供者所支持、并为应用开发者和用户增进持续性和可信度的开放标准。 OAuth相关术语 服务提供方 Service Provider: 一个允许通过...

Global site tag (gtag.js) - Google Analytics