精华帖 (0) :: 良好帖 (10) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-03-27
本帖已转向:http://www.iteye.com/topic/201103
[i] 大家好,今天向大家推荐一个轻量级的java rest 框架 JRest4Guice 项目地址: http://code.google.com/p/jrest4guice/ 这个项目借鉴了http://www.iteye.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(); } } }[/i] 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-03-27
不想用SVN的朋友可以直接下载这个压缩包,里面包含了例子
|
|
返回顶楼 | |
发表时间:2008-03-27
学习中 ,永远支持你 ,谢谢发表好的知识。
|
|
返回顶楼 | |
发表时间:2008-03-27
还是不喜欢@HttpMethod。
为什么需要它呢?难道简单的这样不好么? Contact contact = resourceLocator.getResource(path, Contact.class); contactRepository.addContact(contact); 为什么非要把rest method绑在pojo里? |
|
返回顶楼 | |
发表时间:2008-03-28
ajoo 写道 还是不喜欢@HttpMethod。
为什么需要它呢?难道简单的这样不好么? 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(....); 以下两种方式,哪一种各能让用户接受呢? |
|
返回顶楼 | |
发表时间:2008-03-28
不绑@HttpMethod,那么一般通过url映射的就是Contact这种domain model,也就是rest的资源的概念。
而绑了@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提供不了的,还是不要强迫客户走这个服务模型。 |
|
返回顶楼 | |
发表时间:2008-03-28
ajoo 写道 不绑@HttpMethod,那么一般通过url映射的就是Contact这种domain model,也就是rest的资源的概念。
而绑了@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级就很好地分离开。对于某些需要公用的东西,则可以通过应用的上下文共享。 |
|
返回顶楼 | |
发表时间:2008-03-29
不错。我也不确定我对资源的理解是不是准确。只不过我觉得不绑HttpMethod的话,你可以有灵活性,想domain就domain,想service就service。
另外,不是强迫整合,而是说,嵌入能力是一个比较好的特性。不能嵌入,而非得从头到尾用你的框架就有些局限罢了。 |
|
返回顶楼 | |
发表时间:2008-03-29
最新动态
经过几天的奋战,我们团队又发布了一个基于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小组 |
|
返回顶楼 | |
发表时间:2008-04-15
小建议一下, 能否像webwork一样,使用maven进行管理依赖
这样checkout就不需要下载额外的jar |
|
返回顶楼 | |