使用Jfinal编写的HTTP API应用脚手架项目

项目介绍

实际上这个项目更像一个脚手架,是我多次开发HTTP API应用的经验总结。其中包含了常用的模块(如账户相关,版本更新等),以及本人认为比较好的开发方式和规范。

项目配置

  • version.xml: 存放版本更新信息。entry节点代表一个版本,可设置一到多个,可自由切换。android和iphone节点的default属性表示当前的版本号, 对应entry的version节点值;
  • jdbc.properties: 这个都懂的,存放数据库连接信息;
  • configure.xml: root下的子节点可以随便写,但不能包含属性。在服务器运行过程中,一旦此文件内容发生了变化,会实时生效,无需重启。

举例,从下面的文件中获取prefix节点的值可使用AppProperty.me().getProperty("resource.prefix");读取.

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <resource>
        <!--文件下载的地址前缀-->
        <prefix>http://mlongbo.com/upload</prefix>
    </resource>
</root>

AppConstant类存放诸如resource.prefix的配置常量, AppProperty类用于读取配置,因此建议使用如:

//AppContant类的伪代码
public static final String RES_PREFIX = "resource.prefix";

//AppProperty类的伪代码
public String resourcePrefix() {
    return getProperty(AppConstant.RES_PREFIX);
}

//业务模块中调用。获取配置
String str = AppProperty.me().resourcePrefix();

已实现的常用接口列表

  • 检查账号是否被注册: GET /api/account/checkUser
  • 发送注册验证码: POST /api/account/sendCode
  • 注册: POST /api/account/register
  • 登录: POST /api/account/login
  • 查询用户资料: GET /api/account/profile
  • 修改用户资料: PUT /api/account/profile
  • 修改密码: PUT /api/account/password
  • 修改头像: PUT /api/account/avatar
  • 意见反馈: POST /api/feedback
  • 版本更新检查: GET /api/version/check
  • 文件上传: POST /api/fs/upload

数据响应规范

避免手拼json导致的错误,而使用将Java Bean序列化为JSON的方式。

json数据的根节点使用code字段标识本次响应的状态,如成功、失败、参数缺少或参数值有误,以及服务器错误等;message节点包含服务器响应回来的一些提示信息,主要是方便客户端开发人员在对接接口时定位错误出现的原因。

一般的,响应数据会分为两种,第一种为列表数据,如一组用户信息,另外一种是实体信息,如一条用户信息。data字段值为数组,携带列表数据,datum字段值为json对象,携带实体数据。

如:

//实体数据
{
  "code": 1,
  "message": "成功查询到该用户信息",
  "datum": {
    "name": "jack",
    "lover": "rose",
    "sex": 1,
    "email": "[email protected]"
  }
}
//列表数据
{
  "code": 1,
  "message": "成功查询到两条用户信息",
  "data": [{
    "name": "jack",
    "lover": "rose",
    "sex": 1,
    "email": "[email protected]"
  },{
    "name": "rose",
    "lover": "jack",
    "sex": 0,
    "email": "[email protected]"
  }]
}
//缺少参数
{
  "code": 2,
  "message": "缺少name参数"
}
//参数值有误
{
  "code": 2,
  "message": "sex参数值只能为0或1"
}

//token无效
{
  "code": 422,
  "message": "token值是无效的,请重新登录获取"
}

附上本人常用的几种code值:

  • 1 ok - 成功状态。查询成功,操作成功等;
  • 0 faild - 失败状态
  • 2 argument error - 表示请求参数值有误, 或未携带必需的参数值
  • 3 帐号已存在
  • 4 注册验证码错误
  • 500 error - 服务器错误
  • 404 not found - 请求的资源或接口不存在
  • 422 token error - 未传递token参数,或token值非法

请求参数校验

最多的还是非空检查, 这里重点说一下。因此,我写了一个工具。使用方法如下:

String name = getPara("name");
String lover = getPara("lover");
//使用此方式的前提是当前controller类要继承自BaseAPIController类
if (!notNull(Require.me().put(name, "name参数不能为空").put(lover,"lover参数不能为空"))) {
  return;
}

//效果等同于如下代码:
if (StringUtils.isEmpty(name)) {
  renderJson(new BaseResponse(2, "name参数不能为空"));
  return;
}
if (StringUtils.isEmpty(lover)) {
  renderJson(new BaseResponse(2, "lover参数不能为空"));
  return;
}
//如果没有传递name参数,将会得到如下响应:
{
  "code": 2,
  "message": "name参数不能为空"
}

已实现的公共模块

公共模块实现了基本功能,你可以根据自己的业务需求自由调整数据字段。

Token模块

token, 顾名思义, 表示令牌,用于标识当前用户,同时增加接口的安全性。目前不支持过期策略,也仅支持一个用户一个终端的方式,即用户在一处登录后,再在另一处登录会使之前登录的token失效。

要启用token功能只需要配置TokenInterceptor拦截器类即可。

在使用时,客户端必须在配置了拦截器的接口请求中携带名为"token"的请求参数。

服务端在继承了BaseAPIController类后可以直接调用getUser();函数获取当前用户对象. *注意: * 为了正常地使用getUser函数,必须在登录接口中查出用户对象后,使用类似如下代码建立token与用户对象的映射:

User nowUser = User.user.findFirst(sql, loginName, StringUtils.encodePassword(password, "md5"));

//之后要将token值响应给客户端
String token = TokenManager.getMe().generateToken(nowUser));

文件上传模块

在以往的接口开发过程中,我们都是使用一个统一的文件上传接口上传文件后,服务器响应上传成功后的文件地址,客户端再使用业务接口将文件地址作为参数值发送到服务器。这样做的好处之一是便于服务端将文件统一管理,比如做缓存或CDN;另一方面是为了减小耦合度,比如此时要换成七牛CDN存放静态文件,客户端只需要改写文件上传部分的代码即可。

目前的文件上传接口已实现一或多个文件同时上传,客户端在上传时,必须要为每个文件指定一个请求参数名, 参数名用于在上传结束后,根据服务器的响应数据判断哪些文件是上传失败的,哪些是上传成功的,以及成功后的文件地址是什么。

服务器响应实例如下:

//全部上传成功
{
  "code": 1,
  "message": "success",
  "datum": {
    "file1": "/upload/images/file1.jpg",
    "file2": "/upload/images/file2.jpg"
  }
}
//全部上传失败
{
  "code": 0,
  "message": "failed",
  "failed": ["file1", "file2"]
}
//部分成功,部分失败
{
  "code": 0, //只要有一个文件上传失败,code就会是0
  "failed": ["file3"]
  "datum": {
    "file1": "/upload/images/file1.jpg",
    "file2": "/upload/images/file2.jpg"
  }
}

版本更新和意见反馈

关于版本更新的说明,请查看第一章节中的项目配置,以及API文档;

意见反馈模块比较简单,你可以根据你的业务需求改动数据库字段,以及接口参数。

用户账号模块

这个模块目前实现的接口有:

  • 检查账号是否已注册
  • 发送手机验证码
  • 注册
  • 登录
  • 查询用户资料
  • 修改用户资料
  • 修改密码

如果使用手机验证码功能,你需要改写SMSUtils类的sendCode函数以实现短信发送功能;如果不使用手机验证码功能,可以在注册的接口代码中将验证码检查的功能去掉。在开发调试的过程中,可以访问code.html查询手机验证码。

如果用户表中的字段不能满足你的业务需求,你可以自由增删修改,但同时也需要修改注册和修改用户资料接口。

工具

  • Jetty插件: 无需使用tomcat,直接使用maven的jetty插件启动项目;
  • ant工具: 一般情况下,我们的项目是在服务端使用maven自动构建的,但在开发过程中,代码经常改变需要重新部署,如果重新打包更新又比较麻烦,因此在服务端使用maven命令重新构建后,可直接执行ant命令将已改动的文件copy到tomcat应用目录。所以,若想正常使用该工具,你需要修改build.xml,将tomapp值修改为你的tomcat应用路径。

资源

现有的API接口文档

时间: 2024-10-18 17:06:47

使用Jfinal编写的HTTP API应用脚手架项目的相关文章

使用Gitbook来编写你的Api文档

使用Gitbook来编写你的Api文档 Published on: November 18, 2014 Gitbook是一个很优秀的社区,上面有很多优秀的作者自出版自己的著作,就好像Leanpub,可能很多人喜欢Leanpub,但是我还是喜欢Gitbook,这种类似于Github的原创社区.同时Gitbook还提供一个开源的配套的工具.也许看到此文章的很多人很早就知道Gitbook,但是也许你没有使用过,现在Gitbook已经比较成熟了,功能也比较完善.下面我们首先来介绍下Gitbook的使用.

CK2020微信小程序入门与实战 常用组件API开发技巧项目实战

新年伊始,学习要趁早,点滴记录,学习就是进步! 随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到程序开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了.对于学习有困难不知道如何提升自己可以加扣:1225462853  获取资料. 下载地址:https://pan.baidu.com/s/1hsU5EIS 微信小程序入门与实战 常用组件API开发技巧项目实战 小程序官方正式公告,开放了更多的入口,个人开发者可以申请

推荐一款现代化的脚手架项目《hope-boot》

简介: > 一款现代化的脚手架项目.企业开发?接外包?赚外快?还是学习?这都能满足你,居家必备,值得拥有?? 文档: 使用说明:https://github.com/hope-for/hope-boot/wiki 捐赠: 请作者吃个肉夹馍 :) Links: CI/CD 流程以及原理说明 Github 熊猫哥星球基地 欢迎关注公众号[低调小熊猫] 本文由低调小熊猫一文多发操作发布! 版权归:低调小熊猫所有,禁止转载 原文地址:https://www.cnblogs.com/aodeng/p/11

程序员如何编写好开发技术文档 如何编写优质的API文档工作

编写技术文档,是令众多开发者望而生畏的任务之一.它本身是一件费时费力才能做好的工作.可是大多数时候,人们却总是想抄抄捷径,这样做的结果往往非常令人遗憾的,因为优质的技术文档是决定你的项目是否引人关注的重要因素.无论开源产品或面向开发者的产品,均是如此. 实际上,我想说明的是:对于面向开发者的产品来说,其用户体验中最重要的一环并不是什么主页设计.登录过程.或者SDK下载.真正最重要的是产品的API文档!如果没人知道你的产品如何使用,纵使它巧夺天工,又有何用? 如果你是一个专门从事面向开发者产品设计

第3章2节《MonkeyRunner源码剖析》脚本编写示例: MonkeyDevice API使用示例(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 上一节我们学习了如何通过MonkeyRunner这个类的静态方法waitForConnection来把后台和设备建立好连接,且看到了在建立连接成功后,该方法会返回来一个MonkeyDevice的实例对象.那么这一节我们

第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 在上一节的第一个"增加日记"的示例中,我们并没有看到日记是否真的增加成功了,也就是说当时并没有进行结果比较.其实在MonkeyRunner框架中,测试结果的比较往往都是通过截屏比对来完成的.而截屏比

第3章1节《MonkeyRunner源码剖析》脚本编写示例: MonkeyRunner API使用示例(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. MonkeyRunner这个类可以说是编写monkeyrunner脚本的入口,因为这个类有一个很重要的方法watForConnection,它的作用就是去尝试去把monkeyrunner的后台和指定的设备建立好连接.只有连接上设备了,mo

C4D python插件编写之Doc API系列

BaseDocument.GetData() 未知 BaseDocument.GetDocumentData()未知 BaseDocument.SetDocumentData()未知 BaseDocument.GetSettingsInstance()未知 doc.GetFirstObject() 获取场景中排在第一个的物体 BaseDocument.GetFirstMaterial() 获得首个材质球,例: def main(): firstMat = doc.GetFirstMaterial

struts2学习笔记之六(Action访问servlet的API以及复制项目小技巧)

action和servlet分离使得action代码更加纯洁,与servlet的耦合性也降低了 但是有时候却不得不访问servlet API,比如把数据放到session,application里, 更甚至于添加cookie(response.addCookie()) strust2提供了两种方式访问servlet api 伪访问 借助于ActionContext类 Map<String ,Object > getApplication() 模拟访问http application Map&l