Redkale RESTful 插件介绍
来源:互联网 发布:为什么淘宝店铺搜不到 编辑:程序博客网 时间:2024/05/16 07:28
Redkale 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过程,让开发更加敏捷。
- Redkale RESTful 插件介绍
- Java 微服务框架 Redkale 入门介绍
- RESTFul介绍
- Restful 介绍
- Restful WebService简单介绍
- Restful WebService简单介绍
- Restful风格介绍
- RESTful Web API介绍
- java restful api 介绍
- RestFul服务介绍
- JEESZ RestFul服务介绍
- JEESZ RestFul服务介绍
- JEESZ RestFul服务介绍
- JEESZ RestFul服务介绍
- JEESZ RestFul服务介绍
- JEESZ RestFul服务介绍
- JEESZ RestFul服务介绍
- RestFul服务介绍
- VSCODE git
- 进驻 CSDN
- spring MVC 文件上传
- 学习javaee的第一天
- Android 工具包 xUtils
- Redkale RESTful 插件介绍
- windows编程之线程池
- 养成良好SQL书写习惯
- matplotlib基本绘图参数
- 【杭电oj】4004 - The Frog's Games(STL & 二分 & 贪心)
- iOS 短信验证码倒计时按钮的实现
- The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path 解决方法
- 225. Implement Stack using Queues
- 插入代码,为什么没有行号?????