REST插件介绍
org.redkalex.rest 是基于HTTP服务的REST插件,提供了很简单的REST服务接口方便开发。REST根据加载的Service组件自动生成对应的HttpServlet。其接口比Spring Boot之类的REST服务框架要简化得多,不需要进行注解配置也可以按REST服务加载。
快速上手
为了让REST生效,必须配置 application.xml 中 HTTP 的 <server> 节点的nodeInterceptor属性值为 org.redkalex.rest.RestNodeInterceptor 。
同时必须在<server> 节点 里增加 <rest> 子节点。配置介绍如下:
<application port="5001">
<resources>
<!-- ... -->
</resources>
<!--
nodeInterceptor: 值必须要是 org.redkalex.rest.RestNodeInterceptor,且只能配置在protocol="HTTP"的server节点上,REST服务才会生效。
-->
<server protocol="HTTP" port="6060" nodeInterceptor="org.redkalex.rest.RestNodeInterceptor">
<!--
REST的核心配置项
base: REST服务的BaseServlet,必须是 org.redkalex.rest.RestHttpServlet 的子类,该属性值没有默认值,必须指定。
autoload:默认值"true" 默认值. 加载当前server所能使用的Servce对象;
mustsign:默认值"false" 是否只加载标记为RestController的Service类,默认加载所有可用Service
includes:当autoload="true", 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
excludes:当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
-->
<rest base="org.redkalex.test.rest.SimpleRestServlet" mustsign="false" autoload="true" includes="" excludes="">
<!--
value: Service类名,列出的表示必须被加载的Service对象, 且对象的Resource资源名称只能是""。
-->
<service value="com.xxx.XXXXService"/>
</rest>
<!-- 其他配置... -->
</server>
</application>
通常配置都需要编写一个 org.redkalex.rest.RestHttpServlet 子类,主要用于获取当前用户信息和鉴权,且必须指定具体的User对象类。开发者的实现类可以参考redkale-demo 中的BaseServlet类,以下是一个简单的范例:
public class SimpleRestServlet extends RestHttpServlet<UserInfo> {
@Resource
private UserService userService;
//获取当前用户信息
@Override
protected UserInfo currentUser(HttpRequest req) throws IOException {
String sessionid = req.getSessionid(false);
if (sessionid == null || sessionid.isEmpty()) return null;
return userService.current(sessionid);
}
//普通鉴权
@Override
public boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException {
UserInfo info = currentUser(request);
if (info == null) {
response.addHeader("retcode", RetCodes.RET_USER_UNLOGIN);
response.addHeader("retmessage", "Not Login");
response.setStatus(203);
response.finish("{'success':false, 'message':'Not Login'}");
return false;
} else if (!info.checkAuth(module, actionid)) { // 根据module、actionid进行鉴权
response.addHeader("retcode", RetCodes.RET_USER_AUTH_ILLEGAL);
response.addHeader("retmessage", "No Authority");
response.setStatus(203);
response.finish("{'success':false, 'message':'No Authority'}");
return false;
}
return true;
}
}
编写完 org.redkalex.rest.RestHttpServlet 子类后就需要对Service进行设置,设置需要三大注解:@RestController、@RestMapping、@RestParam。
@RestController :
/**
* 只能依附在Service类上,value默认为Service的类名去掉Service字样的字符串 (如HelloService,的默认路径为 hello)。
*/
@Target({TYPE})
public @interface RestController {
boolean ignore() default false; //是否屏蔽该类的转换
String value() default ""; //模块名, 只能是模板名,不能含特殊字符
boolean repair() default true; //同@WebServlet的repair属性
int module() default 0; //模块ID值,鉴权时用到
}
@RestMapping :
/**
* 只能依附在Service实现类的public方法上
* value默认为"/" + Service的类名去掉Service及后面字样的小写字符串 (如HelloService,的默认路径为/hello)。
*/
@Target({METHOD})
public @interface RestMapping {
boolean ignore() default false; //是否屏蔽该方法的转换
//请求的方法名, 不能含特殊字符
//默认为方法名的小写(若方法名以createXXX、updateXXX、deleteXXX、queryXXX、findXXX且XXXService为Service的类名将只截取XXX之前)
String name() default "";
boolean authignore() default true; //是否跳过鉴权,默认跳过
int actionid() default 0; //操作ID值,鉴权时用到
String contentType() default ""; //设置Response的ContentType 默认值为 text/plain; charset=utf-8
String jsvar() default ""; //以application/javascript输出对象是指明js的对象名,该值存在时则忽略contentType()的值
}
@RestParam :
/**
* 只能依附在Service类的方法的参数上, http请求的参数名
*/
@Target({PARAMETER})
public @interface RestParam {
String value(); //参数名
}
REST的设置方式有两大种: 一种是采用默认REST注解,一种是显式的设置。
第一种方式需要开发者对Service中的方法命名需要遵循一定规则, 如下范例,模块为Hello,Service类命名为HelloService,增删改查的方法采用createHello、deleteHello、updateHello、queryHello或其他xxxHello命名。REST插件加载任何没有标记@RestController、@RestMapping、@RestParam 的Service将按照一定规则生成默认值:
1、@RestController.value() 默认值为Service类名的小写化并去掉service及后面字样, 视为模块名
2、@RestMapping.name() 默认值为Service的方法名小写化并去掉模块名字样
2、@RestParam.value() 如果方法名以find、delete开头且方法的参数只有一个且参数类型是基本数据类型或String,则默认值为"#";若使用Java 8中带上 -parameters 编译项的新特性,默认值为参数名, 若没使用新特性则采用bean、bean2、bean3...的命名规则。
/**
* 类说明:
* Flipper : Source组件中的翻页对象, 只要Service方法中的参数类与该类相同,则不需要设定 @RestParam
* UserInfo :当前用户类, 只要Service方法中的参数类与该类相同,则不需要设定 @RestParam
* HelloEntity: Hello模块的实体类
* HelloBean: Hellow模块实现FilterBean的过滤Bean类
*
*/
@RestController(value = "hello", module = 0, repair = true, ignore = false)
public class HelloService implements Service {
@Resource
private DataSource source;
//增加记录
@RestMapping(name = "create", authignore = true)
public RetResult<HelloEntity> createHello(UserInfo info, @RestParam("bean") HelloEntity entity) { //通过 /hello/create?bean={...} 增加对象
entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
entity.setCreatetime(System.currentTimeMillis());
source.insert(entity);
return new RetResult<>(entity);
}
//删除记录
@RestMapping(name = "delete", authignore = true)
public void deleteHello(@RestParam("#") int id) { //通过 /hello/delete/1234 删除对象
source.delete(HelloEntity.class, id);
}
//修改记录
@RestMapping(name = "update", authignore = true)
public void updateHello(@RestParam("bean") HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
entity.setUpdatetime(System.currentTimeMillis());
source.update(entity);
}
//查询列表
@RestMapping(name = "query", authignore = true)
public Sheet<HelloEntity> queryHello(@RestParam("bean") HelloBean bean, Flipper flipper) { //通过 /hello/query/start:0/size:20?bean={...} 查询列表
return source.querySheet(HelloEntity.class, flipper, bean);
}
//查询单个
@RestMapping(name = "find", authignore = true)
public HelloEntity findHello(@RestParam("#") int id) { //通过 /hello/find/1234 查询对象
return source.find(HelloEntity.class, id);
}
}
根据默认命名规则可以看出,以上范例生成的RestServlet与去掉所有@RestController、@RestMapping、@RestParam后的Service生成的是完全相同的。 REST插件根据Service会动态生成HttpServlet,以上范例生成的HttpServlet如下:
@WebServlet(value = {"/hello/*"}, repair = true)
public class _DynHelloRestServlet extends SimpleRestServlet {
@Resource
private HelloService _service;
@AuthIgnore
@WebAction(url = "/hello/create")
public void create(HttpRequest req, HttpResponse resp) throws IOException {
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
UserInfo user = currentUser(req);
RetResult<HelloEntity> result = _service.createHello(user, bean);
sendRetResult(resp, result);
}
@AuthIgnore
@WebAction(url = "/hello/delete/")
public void delete(HttpRequest req, HttpResponse resp) throws IOException {
int id = Integer.parseInt(req.getRequstURILastPath());
_service.deleteHello(id);
sendRetResult(resp, RetResult.SUCCESS);
}
@AuthIgnore
@WebAction(url = "/hello/update")
public void update(HttpRequest req, HttpResponse resp) throws IOException {
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
_service.updateHello(bean);
sendRetResult(resp, RetResult.SUCCESS);
}
@AuthIgnore
@WebAction(url = "/hello/query")
public void query(HttpRequest req, HttpResponse resp) throws IOException {
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
Flipper flipper = findFlipper(req);
Sheet<HelloEntity> result = _service.queryHello(bean, flipper);
resp.finishJson(result);
}
@AuthIgnore
@WebAction(url = "/hello/find/")
public void find(HttpRequest req, HttpResponse resp) throws IOException {
int id = Integer.parseInt(req.getRequstURILastPath());
HelloEntity bean = _service.findHello(id);
resp.finishJson(bean);
}
}
REST的第二种设置方式是显式的设置, 看如下范例:
/**
* 类说明:
* Flipper : Source组件中的翻页对象
* UserInfo :当前用户类
* HelloEntity: Hello模块的实体类
* HelloBean: Hellow模块实现FilterBean的过滤Bean类
*
*/
public class HelloService implements Service {
@Resource
private DataSource source;
//增加记录
public RetResult<HelloEntity> createHello(UserInfo info, HelloEntity entity) {
entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
entity.setCreatetime(System.currentTimeMillis());
source.insert(entity);
return new RetResult<>(entity);
}
//删除记录
public void deleteHello(int id) { //通过 /hello/delete/1234 删除对象
source.delete(HelloEntity.class, id);
}
//修改记录
public void updateHello(HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
entity.setUpdatetime(System.currentTimeMillis());
source.update(entity);
}
//修改记录
@RestMapping(name = "partupdate") //不能使用updatepart,因为存在update,是updatepart的开头部分,不符合BasedHttpServlet的WebAction规则
public void updateHello(HelloEntity entity, @RestParam("cols") String[] columns) { //通过 /hello/update?bean={...} 修改对象
entity.setUpdatetime(System.currentTimeMillis());
source.updateColumns(entity, columns);
}
//查询Sheet列表
public Sheet<HelloEntity> queryHello(HelloBean bean, Flipper flipper) { //通过 /hello/query/start:0/size:20?bean={...} 查询Sheet列表
return source.querySheet(HelloEntity.class, flipper, bean);
}
//查询List列表
@RestMapping(name = "list")
public List<HelloEntity> queryHello(HelloBean bean) { //通过 /hello/list?bean={...} 查询List列表
return source.queryList(HelloEntity.class, bean);
}
//查询单个
@RestMapping(name = "find")
@RestMapping(name = "jsfind", jsvar = "varhello")
public HelloEntity findHello(@RestParam("#") int id) { //通过 /hello/find/1234 查询对象
return source.find(HelloEntity.class, id);
}
}
转换为RestHttpServlet如下:
@WebServlet(value = {"/hello/*"}, repair = true)
public class _DynHelloRestServlet extends SimpleRestServlet {
@Resource
private HelloService _service;
@AuthIgnore
@WebAction(url = "/hello/create")
public void create(HttpRequest req, HttpResponse resp) throws IOException {
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
UserInfo user = currentUser(req);
RetResult<HelloEntity> result = _service.createHello(user, bean);
sendRetResult(resp, result);
}
@AuthIgnore
@WebAction(url = "/hello/delete/")
public void delete(HttpRequest req, HttpResponse resp) throws IOException {
int id = Integer.parseInt(req.getRequstURILastPath());
_service.deleteHello(id);
sendRetResult(resp, RetResult.SUCCESS);
}
@AuthIgnore
@WebAction(url = "/hello/update")
public void update(HttpRequest req, HttpResponse resp) throws IOException {
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
_service.updateHello(bean);
sendRetResult(resp, RetResult.SUCCESS);
}
@AuthIgnore
@WebAction(url = "/hello/partupdate")
public void partupdate(HttpRequest req, HttpResponse resp) throws IOException {
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
String[] cols = req.getJsonParameter(String[].class, "cols");
_service.updateHello(bean, cols);
sendRetResult(resp, RetResult.SUCCESS);
}
@AuthIgnore
@WebAction(url = "/hello/query")
public void query(HttpRequest req, HttpResponse resp) throws IOException {
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
Flipper flipper = findFlipper(req);
Sheet<HelloEntity> result = _service.queryHello(bean, flipper);
resp.finishJson(result);
}
@AuthIgnore
@WebAction(url = "/hello/list")
public void list(HttpRequest req, HttpResponse resp) throws IOException {
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
List<HelloEntity> result = _service.queryHello(bean);
resp.finishJson(result);
}
@AuthIgnore
@WebAction(url = "/hello/find/")
public void find(HttpRequest req, HttpResponse resp) throws IOException {
int id = Integer.parseInt(req.getRequstURILastPath());
HelloEntity bean = _service.findHello(id);
resp.finishJson(bean);
}
@AuthIgnore
@WebAction(url = "/hello/jsfind/")
public void jsfind(HttpRequest req, HttpResponse resp) throws IOException {
int id = Integer.parseInt(req.getRequstURILastPath());
HelloEntity bean = _service.findHello(id);
sendJsResult(resp, "varhello", bean);
}
}
REST插件让开发者省去了编写HttpServlet过程,让开发更加敏捷。
相关推荐
以 Convention 插件为基础,Struts 2.1 又新增了 REST 插件,允许 Struts 2 应用对外提供 REST 服务。REST 插件也无需使用 XML 进行配置管理。Struts 2.1 通过 REST 插件完全可以提供让人和机器客户端共同使用的资源...
chrome插件Advanced Rest Client来调试RESTFul chrome插件Advanced Rest Client来调试RESTFul 可在360浏览器使用
在压缩包中的“使用说明.txt”文件中,详细介绍了如何使用Google Simple REST Client进行API测试。例如: 1. **创建新请求**:点击插件图标,输入目标URL和HTTP方法。 2. **设置请求头**:在请求头区域添加键值对,...
在压缩包内,"1.rtf"可能是一个包含详细使用指南或者插件介绍的文档,用户可以通过阅读它来了解如何安装和操作插件。而"chromecj.com"可能是插件的官方网站地址,用户可以通过访问这个网站获取最新的插件版本、更新...
标签中提到的"struts2插件 rest例子"进一步强调了这个示例项目是关于Struts2 REST插件的实战应用,对于初学者或者需要在现有项目中添加REST功能的开发者来说,这是一个很好的学习和参考资源。 压缩包中的"RestDemo...
安装 REST 插件非常简单,只需按如下步骤进行即可: 将 Struts 2 项目下 struts2-convention-plugin-2.1.6.jar、struts2-rest-plugin-2.1.6.jar 两个 JAR 包复制到 Web 应用的 WEB-INF/lib 路径下。 由于 Struts 2 ...
struts2.1.6 convertion插件(即注释方式配置)的hello...rest插件例子 默认调用 create()方法 struts2.1.6 vistor校验例子 都是我测试例子,写到一块了 有点乱 哪为高手给我说下 rest-plugin有什么好处 项目中有说明文件
本文将详细介绍如何利用谷歌浏览器插件Advanced REST Client (ARC)进行HTTP REST API的测试和调试。 首先,让我们了解什么是REST API。REST(Representational State Transfer)是一种网络应用程序的设计风格和开发...
谷歌REST插件是一款专为开发者设计的工具,它允许用户在谷歌浏览器中直接对Java后台服务进行RESTful API的调试。这款插件极大地简化了Web服务接口测试过程,使得前端和后端开发人员能够更有效地协作,快速定位并解决...
**REST客户端谷歌插件**是一种强大的工具,专为在谷歌浏览器上进行API接口的调试和开发而设计。这款插件简化了与RESTful服务交互的过程,使得开发者无需离开浏览器就能发送HTTP请求并查看响应,极大地提高了开发效率...
为了弥补这一不足,我们可以开发或使用一个插件来扩展REST API,添加文章的特色图片字段。 标题所提到的"WordPress插件:给REST API 新增文章特色图片(缩略图)字段"正是针对这个问题的一个解决方案。特色图片...
Rest client是用来调试REST风格的Web服务,接收POST, GET, PUT...因此介绍一下使用插件的安装与使用。谷歌浏览器advance-rest-client插件安装, 包含所有文档Advanced-REST-client3.1.9 和 启动所需的 definitions.json
Restlet Client插件基于谷歌浏览器的扩展程序机制开发,通过提供直观的用户界面和丰富的功能,帮助用户快速构建和执行API请求。该插件支持多种HTTP方法(如GET、POST、PUT、DELETE等),并提供详细的请求和响应信息...
"Advanced REST Client"是一款在Chrome浏览器上广泛使用的插件,专为开发者设计,方便他们进行API接口测试和调试。这款插件提供了高级的RESTful API交互功能,支持HTTP/HTTPS协议,可帮助开发者轻松发送GET、POST、...
今天给大家介绍的这款网页调试工具不仅可以调试简单的css、html、脚本等简单的网页基本信息,它还可以发送几乎所有类型的HTTP请求!Postman在发送网络HTTP请求方面可以说是Chrome插件类产品中的代表产品之一。
谷歌插件-Advanced REST Client 和被国内墙所挡住的definitions.json
Chrome插件Restlet Client - REST API Testing是一款非常实用的工具,专为Web API的调试和测试设计。这款插件支持多种HTTP方法(如GET、POST、PUT、DELETE等),并提供了丰富的功能,使得API测试过程更加高效和便捷...
**高级REST客户端(Advanced REST Client)的definitions插件详解** 高级REST客户端(Advanced REST Client,简称ARC)是一款功能强大的Chrome浏览器扩展,专为开发者设计,用于测试和调试RESTful Web服务。它允许用户...
DHC-REST-HTTP-API-Client,DHC是一款可以帮助用户使用chrome插件模拟HTTP客户端发送测试数据到服务器的谷歌浏览器插件。 在chrome中安装了DHC插件以后,就可在服务器端代码初步完成的时候,使用DHC进行数据测试,...
Chrome基于REST的Web服务客户端插件是一款非常实用的开发者工具,尤其对于那些频繁与RESTful API打交道的IT专业人员来说,它提供了一种方便、快捷的方式来测试和调试接口。REST(Representational State Transfer)...