2008-03-27
向大家推荐一个轻量级的java rest 框架 JRest4Guice
关键字: rest
本帖已转向:http://www.javaeye.com/topic/201103
大家好,今天向大家推荐一个轻量级的java rest 框架 JRest4Guice
项目地址: http://code.google.com/p/jrest4guice/
这个项目借鉴了http://www.javaeye.com/topic/170289的一些思想和代码。本人在此先谢了。
特点:
1. 基于GUICE
2. 零配置式服务声明
@Restful(uri = "/contacts")
public class ContactListRestService
3. 服务的自动扫描注册
4. 非侵入式风格,用户不需要实现特定的接口来实现Restful服务
用户只要在指定的POJO上:
1. 声明为@Restful,并指明访问的URI格式
2. 在指定的方法上声明为@HttpMethod
5. 支持Rest的Post. Get. Put. Delete操作
用户在指定的方法上通过@HttpMethod注解来声明方法的类型,如下:
@HttpMethod(type = HttpMethodType.POST)
public String createContact(String name, @RequestParameter("homePhone") String homePhone, @ModelBean Contact contact)
@HttpMethod
public String getContact(@FirstResult int first, @MaxResults int max)
注:如果没有提供HttpMethodType类型的声明,系统会自动根据方法名称的前缀来自动识别(方法名必须以get/post/put/delete开头)
6. 灵活的注入
6.1. 支持HttpServletRequest. HttpServletResponse. ModelMap的注入
@Inject
private ModelMap modelMap;
@Inject
private HttpServletRequest request;
@Inject
private HttpServletResponse response;
6.2. 支持参数的自动注入
方法中的参数可以由系统自动注入,如下:
public String createContact(String name, @RequestParameter("homePhone") String homePhone, @ModelBean Contact contact)
注:如果参数没有任何注解,系统默认获取上下文ID为参数名称的参数值,否则通过@RequestParameter注解指定的参数名称来获取,@ModelBean可以将上下文中的参数转换成指定参数类型的Java bean
6.3. 支持对JndiResource的注入
示例代码:
大家好,今天向大家推荐一个轻量级的java rest 框架 JRest4Guice
项目地址: http://code.google.com/p/jrest4guice/
这个项目借鉴了http://www.javaeye.com/topic/170289的一些思想和代码。本人在此先谢了。
特点:
1. 基于GUICE
2. 零配置式服务声明
@Restful(uri = "/contacts")
public class ContactListRestService
3. 服务的自动扫描注册
4. 非侵入式风格,用户不需要实现特定的接口来实现Restful服务
用户只要在指定的POJO上:
1. 声明为@Restful,并指明访问的URI格式
2. 在指定的方法上声明为@HttpMethod
5. 支持Rest的Post. Get. Put. Delete操作
用户在指定的方法上通过@HttpMethod注解来声明方法的类型,如下:
@HttpMethod(type = HttpMethodType.POST)
public String createContact(String name, @RequestParameter("homePhone") String homePhone, @ModelBean Contact contact)
@HttpMethod
public String getContact(@FirstResult int first, @MaxResults int max)
注:如果没有提供HttpMethodType类型的声明,系统会自动根据方法名称的前缀来自动识别(方法名必须以get/post/put/delete开头)
6. 灵活的注入
6.1. 支持HttpServletRequest. HttpServletResponse. ModelMap的注入
@Inject
private ModelMap modelMap;
@Inject
private HttpServletRequest request;
@Inject
private HttpServletResponse response;
6.2. 支持参数的自动注入
方法中的参数可以由系统自动注入,如下:
public String createContact(String name, @RequestParameter("homePhone") String homePhone, @ModelBean Contact contact)
注:如果参数没有任何注解,系统默认获取上下文ID为参数名称的参数值,否则通过@RequestParameter注解指定的参数名称来获取,@ModelBean可以将上下文中的参数转换成指定参数类型的Java bean
6.3. 支持对JndiResource的注入
示例代码:
@Restful(uri = { "/contact", "/contact/{contactId}" })
public class ContactRestService {
@Inject
private ModelMap modelMap;
@Inject
private HttpServletRequest request;
@Inject
private HttpServletResponse response;
@Inject
@JndiResource(jndi = "test/ContactService")
private ContactService service;
@HttpMethod(type = HttpMethodType.POST)
public String createContact(String name, @RequestParameter("homePhone") String homePhone, @ModelBean Contact contact) {
if (contact == null)
return HttpResult.createFailedHttpResult("-1","联系人信息不能为空").toJson();
String contactId = null;
try {
contactId = this.service.createContact(contact);
return HttpResult.createSuccessfulHttpResult(contactId).toJson();
} catch (RemoteException e) {
return HttpResult.createFailedHttpResult(e.getClass().getName(),e.getMessage()).toJson();
}
}
@HttpMethod
public String putContact(@RequestParameter("contactId")
String contactId, @ModelBean
Contact contact) {
if (contactId == null)
return HttpResult.createFailedHttpResult("-1","没有指定对应的联系人标识符").toJson();
try {
this.service.updateContact(contact);
return HttpResult.createSuccessfulHttpResult("修改成功").toJson();
} catch (RemoteException e) {
return HttpResult.createFailedHttpResult(e.getClass().getName(),e.getMessage()).toJson();
}
}
@HttpMethod
public String getContact(@RequestParameter("contactId")
String contactId) {
try {
Contact contactDto = this.service.findContactById(contactId);
return HttpResult.createSuccessfulHttpResult(contactDto).toJson();
} catch (Exception e) {
return HttpResult.createFailedHttpResult(e.getClass().getName(),e.getMessage()).toJson();
}
}
@HttpMethod
public String deleteContact(@RequestParameter("contactId")
String contactId) {
try {
this.service.deleteContact(contactId);
return HttpResult.createSuccessfulHttpResult("删除成功").toJson();
} catch (Exception e) {
return HttpResult.createFailedHttpResult(e.getClass().getName(),e.getMessage()).toJson();
}
}
}
评论
agapple
2008-04-15
小建议一下, 能否像webwork一样,使用maven进行管理依赖
这样checkout就不需要下载额外的jar
这样checkout就不需要下载额外的jar
cnoss
2008-03-29
最新动态
经过几天的奋战,我们团队又发布了一个基于Guice的JPA实现--Jpa4Guice 0.1 预览版,示例如下:
1、业务接口
2、业务实现
3、Rest的控制类
@Restful(uri = { "/contact", "/contact/{contactId}" })
public class ContactController {
@Inject
private ContactService service;//注入的业务接口
@HttpMethod(type = HttpMethodType.POST)
public String createContact(String name, @RequestParameter("homePhone") String homePhone, @ModelBean Contact contact) {}
...
...
}
===========================================
我们会在下一个版本中增加动态DAO的支持
===========================================
注:
1、由于最近的更新比较频繁,所以没有打包,有需要的朋友请从SVN上直接下载原代码,源代码中有详细的例子。
2、示例已经可以运行jboss/tomcat/jetty服务器上,已经完全脱离了EJB环境。
谢谢大家的参与和批评。
-- cnoss小组
经过几天的奋战,我们团队又发布了一个基于Guice的JPA实现--Jpa4Guice 0.1 预览版,示例如下:
1、业务接口
@ImplementedBy(ContactServiceBean.class)
public interface ContactService {
public String createContact(Contact contact) throws RemoteException;
public List<Contact> listContacts(int first,int max) throws RemoteException;
public Contact findContactById(String contactId) throws RemoteException;
public void updateContact(Contact contact) throws RemoteException;
public void deleteContact(String contactId) throws RemoteException;
}
2、业务实现
public class ContactServiceBean implements ContactService {
@Inject
private EntityManager entityManager;//JPA实体管理器的注入
@Transactional//事务声明
public String createContact(Contact contact) throws RemoteException {
if (contact == null)
throw new RemoteException("联系人的内容不能为空");
if(this.entityManager.createNamedQuery("byName").setParameter("name", contact.getName()).getResultList().size()>0){
throw new RemoteException("联系人的姓名相同,请重新输入");
}
this.entityManager.persist(contact);
return contact.getId();
}
@Transactional//事务声明
public void deleteContact(String contactId) throws RemoteException {
Contact contact = this.findContactById(contactId);
if (contact == null)
throw new RemoteException("联系人不存在");
this.entityManager.remove(contact);
}
@Transactional//事务声明
public Contact findContactById(String contactId) throws RemoteException {
return this.entityManager.find(Contact.class, contactId);
}
@Transactional//事务声明
public List<Contact> listContacts(int first, int max)
throws RemoteException {
return this.entityManager.createNamedQuery("list").setFirstResult(first)
.setMaxResults(max).getResultList();
}
@Transactional//事务声明
public void updateContact(Contact contact) throws RemoteException {
if (contact == null)
throw new RemoteException("联系人的内容不能为空");
this.entityManager.merge(contact);
}
}
3、Rest的控制类
@Restful(uri = { "/contact", "/contact/{contactId}" })
public class ContactController {
@Inject
private ContactService service;//注入的业务接口
@HttpMethod(type = HttpMethodType.POST)
public String createContact(String name, @RequestParameter("homePhone") String homePhone, @ModelBean Contact contact) {}
...
...
}
===========================================
我们会在下一个版本中增加动态DAO的支持
===========================================
注:
1、由于最近的更新比较频繁,所以没有打包,有需要的朋友请从SVN上直接下载原代码,源代码中有详细的例子。
2、示例已经可以运行jboss/tomcat/jetty服务器上,已经完全脱离了EJB环境。
谢谢大家的参与和批评。
-- cnoss小组
ajoo
2008-03-29
不错。我也不确定我对资源的理解是不是准确。只不过我觉得不绑HttpMethod的话,你可以有灵活性,想domain就domain,想service就service。
另外,不是强迫整合,而是说,嵌入能力是一个比较好的特性。不能嵌入,而非得从头到尾用你的框架就有些局限罢了。
另外,不是强迫整合,而是说,嵌入能力是一个比较好的特性。不能嵌入,而非得从头到尾用你的框架就有些局限罢了。
y_franky
2008-03-28
ajoo 写道
不绑@HttpMethod,那么一般通过url映射的就是Contact这种domain model,也就是rest的资源的概念。
而绑了@HttpMethod,那么写的就是你例子中的ContactService的这种服务模型。
那么前者怎么处理put/create/get呢?
很灵活,可以用你提出的Restable的接口,但是这个接口不是框架定义的,而是客户自己定义的,然后客户就这么调用:
也可以,干脆不搞什么接口。比如我的应用还是传统的servlet或者struts action。只想在某个servlet里面嵌入rest的url映射,那么在某个FooServlet的doGet()里面,我就这么做:
而如果绑了@HttpMethod,框架做的事情更多,更大,更复杂,但是客户程序的灵活性就低了,你只能针对服务模型设计,必须在FooService里面处理get/put,而不能交给系统别的部分去做。
所以我觉得,除非@HttpMethod有特别突出的优点是domain model提供不了的,还是不要强迫客户走这个服务模型。
而绑了@HttpMethod,那么写的就是你例子中的ContactService的这种服务模型。
那么前者怎么处理put/create/get呢?
很灵活,可以用你提出的Restable的接口,但是这个接口不是框架定义的,而是客户自己定义的,然后客户就这么调用:
Restable restable = resourceLocator.getResource(path, Restable.class); restable.get();
也可以,干脆不搞什么接口。比如我的应用还是传统的servlet或者struts action。只想在某个servlet里面嵌入rest的url映射,那么在某个FooServlet的doGet()里面,我就这么做:
Foo foo = resourceLocator.getResource(request.getPathInfo(), Foo.class); response.getWriter().write(foo.getName());
而如果绑了@HttpMethod,框架做的事情更多,更大,更复杂,但是客户程序的灵活性就低了,你只能针对服务模型设计,必须在FooService里面处理get/put,而不能交给系统别的部分去做。
所以我觉得,除非@HttpMethod有特别突出的优点是domain model提供不了的,还是不要强迫客户走这个服务模型。
嗯,我大概明白你的想法了,理由确实也是很充分的。不过有些地方,我的看法与你有些不同。
1、对REST上资源的理解,我不认为它必须与Domain Model对应,我只会把它们看为有固定结构的数据体,当然它们也可以和Domain Model对应,但更多时候它们可能只是某种数据视图。所以我只会把它们看成是某种有含义受约束的URI,而不会将它们和Domain Model画等号。
2、由于有第一点的观点,所以我认为REST内资源的(GET, POST, PUT, DELETE)的含义是可由应用定义的,也不一定需要全部实现。
3、至于和其它MVC整合,我觉得不需要强迫要在其它MVC内完成REST的工作,两者完全可以在URI级就很好地分离开。对于某些需要公用的东西,则可以通过应用的上下文共享。
ajoo
2008-03-28
不绑@HttpMethod,那么一般通过url映射的就是Contact这种domain model,也就是rest的资源的概念。
而绑了@HttpMethod,那么写的就是你例子中的ContactService的这种服务模型。
那么前者怎么处理put/create/get呢?
很灵活,可以用你提出的Restable的接口,但是这个接口不是框架定义的,而是客户自己定义的,然后客户就这么调用:
也可以,干脆不搞什么接口。比如我的应用还是传统的servlet或者struts action。只想在某个servlet里面嵌入rest的url映射,那么在某个FooServlet的doGet()里面,我就这么做:
而如果绑了@HttpMethod,框架做的事情更多,更大,更复杂,但是客户程序的灵活性就低了,你只能针对服务模型设计,必须在FooService里面处理get/put,而不能交给系统别的部分去做。
所以我觉得,除非@HttpMethod有特别突出的优点是domain model提供不了的,还是不要强迫客户走这个服务模型。
而绑了@HttpMethod,那么写的就是你例子中的ContactService的这种服务模型。
那么前者怎么处理put/create/get呢?
很灵活,可以用你提出的Restable的接口,但是这个接口不是框架定义的,而是客户自己定义的,然后客户就这么调用:
Restable restable = resourceLocator.getResource(path, Restable.class); restable.get();
也可以,干脆不搞什么接口。比如我的应用还是传统的servlet或者struts action。只想在某个servlet里面嵌入rest的url映射,那么在某个FooServlet的doGet()里面,我就这么做:
Foo foo = resourceLocator.getResource(request.getPathInfo(), Foo.class); response.getWriter().write(foo.getName());
而如果绑了@HttpMethod,框架做的事情更多,更大,更复杂,但是客户程序的灵活性就低了,你只能针对服务模型设计,必须在FooService里面处理get/put,而不能交给系统别的部分去做。
所以我觉得,除非@HttpMethod有特别突出的优点是domain model提供不了的,还是不要强迫客户走这个服务模型。
y_franky
2008-03-28
ajoo 写道
还是不喜欢@HttpMethod。
为什么需要它呢?难道简单的这样不好么?
为什么非要把rest method绑在pojo里?
为什么需要它呢?难道简单的这样不好么?
Contact contact = resourceLocator.getResource(path, Contact.class); contactRepository.addContact(contact);
为什么非要把rest method绑在pojo里?
注解的方式是把资源看成是URI的映射,如果把资源看成是具体的类,虽然说可以通过超类继承很多基础方法,但带来的是对类的扩展无法更方便的支持。
如果不使用@HttpMethod,也许我们会这样:
1、让每个Rest 服务必须要实现一个特定的接口,如:
public interface RestAble{
public void get();
public void post();
public void put();
public void delete();
}
2、通过一种方法名的约束,让具体的Rest方法前必须以类似get/post/put/delete的前缀
而引入@HttpMethod,可以:
1、从平台特定的API中解放出来,不要实现任何带限制的接口,就像EJB2.0那样要求每个EJB实现home/remote接口一样。
2、不会限制用户的业务方法的命名,如下:
public void registUser(....); public void postUser(....);
以下两种方式,哪一种各能让用户接受呢?
ajoo
2008-03-27
还是不喜欢@HttpMethod。
为什么需要它呢?难道简单的这样不好么?
为什么非要把rest method绑在pojo里?
为什么需要它呢?难道简单的这样不好么?
Contact contact = resourceLocator.getResource(path, Contact.class); contactRepository.addContact(contact);
为什么非要把rest method绑在pojo里?
backbase
2008-03-27
学习中 ,永远支持你 ,谢谢发表好的知识。
cnoss
2008-03-27
不想用SVN的朋友可以直接下载这个压缩包,里面包含了例子
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 409 次
- 性别:

- 来自: 广州

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
一个Java的Restful服务框 ...
越来越人性化了,看来不用都不行了。
-- by netbeans -
一个Java的Restful服务框 ...
最新动态 JRest4Guice中增加了对Get方法的缓存机制,实现了对动态资源 ...
-- by cnoss -
一个Java的Restful服务框 ...
Enigma 写道为什么没有办法访问DEMO网站? ,这几天去外省出差,家里的 ...
-- by cnoss -
一个Java的Restful服务框 ...
jeff_yuchang 写道cnoss 写道更新通知 大家好,为了提高JRe ...
-- by cnoss -
一个Java的Restful服务框 ...
为什么没有办法访问DEMO网站?
-- by Enigma






评论排行榜