1 前提

  由于近期工作的需要,要把RESTLET应用到项目中,于是在网上参考了一些资料的基础上,实践了一个关于RESTLET接口的小例子。

  Restlet的思想是:HTTP客户端与HTTP服务器之间的差别,对架构来说无所谓。一个软件应可以既充当Web客户端又充当Web服务器,而无须采用两套完全不同的APIs。

  Restlet提供了多个版本:Java SE、Java EE、android、Google AppEngine、Google Web Toolkit、Android。这里我们使用的是jee版本。

  RESTLET的实现可以采用JAX-RS方式,也可以采用其他方式,见:

http://www.iteye.com/topic/85928

本例子是采用JAX-RS的API开发的,这种方式提供了一种基于注解的模型来描述分布式资源,可以利用注解的功能提供资源的位置、传递等。可以在一个Resource类中同时对外提供多个rest接口服务。具体的实现步骤见如下章节。

2 实例开发

2.1 工程说明

此处可以建立一个web工程,也可以建立一个JAVASE工程,如何应用就UP TO YOU了,此处的例子只是为了梳理下RESTLET的开发流程,不涉及到web界面的应用,所以就建立了一个普通的JAVASE的工程。工程的结构图如下:

我们的工程分为如下几个部分:Server启动模块、Application模块、modle模块、REST接口实现的resource模块和客户端模块。

工程所依赖的jar包,是最基本的这个6个包,因为数据的传输使用的JSON,所以json包是必须的,如果想扩展功能,请自行添加其余的包。

2.2 Server端启动部分

RestJaxRsServer类的代码如下:

 package com.scott.restlet;

 import org.restlet.Component;
import org.restlet.data.Protocol; import com.scott.restlet.application.RestJaxRsApplication; public class RestJaxRsServer { public static void main(String[] args) throws Exception {
Component component = new Component();
component.getServers().add(Protocol.HTTP, 8082);
component.getDefaultHost().attach(new RestJaxRsApplication(null));
component.start(); System.out.println("The restlet server started ...");
}
}

此代码中指定了我们的HTTP的绑定端口,地址就是本地默认的ip。另外,代码中有一个RestJaxRsApplication,这是每个Application能够管理一组restlet接口。

2.3 Application部分

在application包中有两个类,一个是RestJaxRsApplication类,继承了org.restlet.ext.jaxrs.JaxRsApplication,作为运行类,用于初始化REST的运行环境,其代码如下:

 package com.scott.restlet.application;

 import org.restlet.Context;
import org.restlet.ext.jaxrs.JaxRsApplication; public class RestJaxRsApplication extends JaxRsApplication { public RestJaxRsApplication(Context context) {
super(context);
this.add(new MyApplication());
} }

另外一个是MyApplication,作为应用类,继承了javax.ws.rs.core.Application,这里面绑定了我们的RESTLET的接口RESOURCE类,可以将多个资源绑定在HashSet中,代码如下:

 package com.scott.restlet.application;

 import java.util.HashSet;
import java.util.Set; import javax.ws.rs.core.Application; import com.scott.restlet.resource.StudentResource;
import com.scott.restlet.resource.TeacherResource; public class MyApplication extends Application { @Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<Class<?>>(); resources.add(StudentResource.class);
resources.add(TeacherResource.class); return resources;
} }

2.4 模型部分

此实例的操作模型比较简单,就是一个Student类和一个Teacher类,代码如下:

Student:

 package com.scott.restlet.modle;

 public class Student {

     private int id;
private String name;
private int sex;
private int age;
private int grade; public int getGrade() {
return grade;
} public void setGrade(int grade) {
this.grade = grade;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getSex() {
return sex;
} public void setSex(int sex) {
this.sex = sex;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
}
}

Teacher:

 package com.scott.restlet.modle;

 public class Teacher {

     private int id;
private String name;
private int sex;
private int age;
private String subject; public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}

2.5 RESOURCE部分

这部分是我们的RESTLET接口实现部分,此处我们有两个接口实现类,一个是StudentResource,一个是TeacherResource,分别对外提供不同的REST接口服务。至于StorageOperator类,把它当做一个内存数据库好了,其实就是一个HashMap,StudentResource和TeacherResource的操作会在StorageOperator类中具体实现。代码如下:

StudentResource:

 package com.scott.restlet.resource;

 import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import org.restlet.data.Form;
import org.restlet.representation.Representation; import com.scott.restlet.modle.Student; @Path("/TestRestlet/student/")
public class StudentResource { @GET
@Path("{id}/json")
@Produces("application/json")
public Student getStudentJson(@PathParam("id") int id) {
return StorageOperator.findStudent(id);
} @POST
@Path("add")
public String addStudent(Representation entity) { //get parameters from client
Form form = new Form(entity);
String name = form.getFirstValue("name");
int grade = Integer.parseInt(form.getFirstValue("grade"));
int sex = Integer.parseInt(form.getFirstValue("sex"));
int age = Integer.parseInt(form.getFirstValue("age")); Student student = new Student();
student.setGrade(grade);
student.setName(name);
student.setSex(sex);
student.setAge(age); int id = StorageOperator.studentID + 1;
student.setId(id);
return String.valueOf(StorageOperator.addStudent(student));
} @PUT
@Path("update")
public String updateStudent(Representation entity) {
Form form = new Form(entity); int id = Integer.parseInt(form.getFirstValue("id"));
Student student = StorageOperator.findStudent(id); if (student == null) {
return "null";
}else{
String name = form.getFirstValue("name");
int grade = Integer.parseInt(form.getFirstValue("grade"));
int sex = Integer.parseInt(form.getFirstValue("sex"));
int age = Integer.parseInt(form.getFirstValue("age")); student.setGrade(grade);
student.setName(name);
student.setSex(sex);
student.setAge(age); return String.valueOf(StorageOperator.updateStudent(student));
}
} @DELETE
@Path("delete/{id}")
public String deleteStudent(@PathParam("id") int id) {
int status = StorageOperator.deleteStudent(id);
return String.valueOf(status);
} }

TeacherResource:

 package com.scott.restlet.resource;

 import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import org.restlet.data.Form;
import org.restlet.representation.Representation; import com.scott.restlet.modle.Teacher; @Path("/TestRestlet/teacher/")
public class TeacherResource {
@GET
@Path("{id}/json")
@Produces("application/json")
public Teacher getTeacherJson(@PathParam("id") int id) {
return StorageOperator.findTeacher(id);
} @POST
@Path("add")
public String addTeacher(Representation entity) { //get parameters from client
Form form = new Form(entity);
String name = form.getFirstValue("name");
String subject = form.getFirstValue("subject");
int sex = Integer.parseInt(form.getFirstValue("sex"));
int age = Integer.parseInt(form.getFirstValue("age")); Teacher teacher = new Teacher();
teacher.setSubject(subject);
teacher.setName(name);
teacher.setSex(sex);
teacher.setAge(age); int id = StorageOperator.teacherID + 1;
teacher.setId(id);
return String.valueOf(StorageOperator.addTeacher(teacher));
} @PUT
@Path("update")
public String updateTeacher(Representation entity) {
Form form = new Form(entity); int id = Integer.parseInt(form.getFirstValue("id"));
Teacher teacher = StorageOperator.findTeacher(id); if (teacher == null) {
return "null";
}else{
String name = form.getFirstValue("name");
String subject = form.getFirstValue("subject");
int sex = Integer.parseInt(form.getFirstValue("sex"));
int age = Integer.parseInt(form.getFirstValue("age")); teacher.setSubject(subject);
teacher.setName(name);
teacher.setSex(sex);
teacher.setAge(age); return String.valueOf(StorageOperator.updateTeacher(teacher));
}
} @DELETE
@Path("delete/{id}")
public String deleteTeacher(@PathParam("id") int id) {
int status = StorageOperator.deleteTeacher(id);
return String.valueOf(status);
}
}

StorageOperator:

 package com.scott.restlet.resource;

 import java.util.HashMap;

 import com.scott.restlet.modle.Student;
import com.scott.restlet.modle.Teacher; public class StorageOperator {
public static int studentID = 1;
public static int teacherID = 1; public static HashMap<Integer, Student> students = new HashMap<Integer, Student>();
public static HashMap<Integer, Teacher> teachers = new HashMap<Integer, Teacher>(); static {
Student student = new Student();
student.setId(1);
student.setGrade(3);
student.setName("Scott");
student.setSex(0);
student.setAge(18);
students.put(student.getId(), student); Teacher teacher = new Teacher();
teacher.setId(1);
teacher.setSubject("MATH");
teacher.setName("Toney");
teacher.setSex(1);
teacher.setAge(27);
teachers.put(teacher.getId(), teacher);
} public static Student findStudent(int id) {
return students.get(id);
} public static int addStudent(Student student) {
students.put(student.getId(), student);
return student.getId();
} public static int updateStudent(Student student) {
return addStudent(student);
} public static int deleteStudent(int id) {
if (students.get(id) != null) {
students.remove(id);
return 1;
}
return 0;
} public static Teacher findTeacher(int id) {
return teachers.get(id);
} public static int addTeacher(Teacher teacher) {
teachers.put(teacher.getId(), teacher);
return teacher.getId();
} public static int updateTeacher(Teacher teacher) {
return addTeacher(teacher);
} public static int deleteTeacher(int id) {
if (teachers.get(id) != null) {
teachers.remove(id);
return 1;
}
return 0;
} }

在类的上面标注的PATH注解,作为全局的一个路径变量,方法上部的PATH注解都以类注解作为相对路径。并且,Produce表示返回的数据格式,此处是JSON类型。至于GET和POST,可以简单的理解为:

POST   /uri     创建

DELETE /uri/xxx 删除

PUT    /uri/xxx 更新或创建

GET    /uri/xxx 查看

2.6 客户端部分

客户端的访问REST接口,可以通过浏览器来输入url访问,也可以通过代码来访问,通过代码来访问的代码此处封装在了Client类中,代码如下:

StudentOperateClient:

 package com.scott.restlet.client;

 import java.io.IOException;

 import org.restlet.data.Form;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException; public class StudentOperateClient {
public static void testGetStudent(String url) {
ClientResource client = new ClientResource(url + "student/1/json");
try {
System.out.println("Student get " + client.get().getText());
} catch (ResourceException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} public static void testAddStudent(String url) {
ClientResource client = new ClientResource(url + "student/add");
try {
Form form = new Form();
form.add("name", "Scott007");
form.add("grade", "3");
form.add("sex", "0");
form.add("age", "15"); String id = client.post(form.getWebRepresentation()).getText(); System.out.println("Student add " + id);
} catch (Exception e) {
e.printStackTrace();
}
} public static void testUpdateStudent(String url) {
ClientResource client = new ClientResource(url + "student/update");
try {
Form form = new Form();
form.add("name", "Scott007");
form.add("grade", "4");
form.add("sex", "0");
form.add("id", "1");
form.add("age", "16"); String id = client.put(form.getWebRepresentation()).getText(); System.out.println("Student update " + id);
} catch (Exception e) {
e.printStackTrace();
}
} public static void testDeleteStudent(String url) {
ClientResource client = new ClientResource(url + "student/delete/1");
try {
System.out.println("Student delete " + client.delete().getText());
} catch (ResourceException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

TeacherOperateClient:

 package com.scott.restlet.client;

 import java.io.IOException;

 import org.restlet.data.Form;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException; public class TeacherOperateClient {
public static void testGetTeacher(String url) {
ClientResource client = new ClientResource(url + "teacher/1/json");
try {
System.out.println("Teacher get " + client.get().getText());
} catch (ResourceException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} public static void testAddTeacher(String url) {
ClientResource client = new ClientResource(url + "teacher/add");
try {
Form form = new Form(); form.add("name", "Scott008");
form.add("subject", "MATH");
form.add("sex", "0");
form.add("age", "27"); String id = client.post(form.getWebRepresentation()).getText(); System.out.println("Teacher add " + id);
} catch (Exception e) {
e.printStackTrace();
}
} public static void testUpdateTeacher(String url) {
ClientResource client = new ClientResource(url + "teacher/update");
try {
Form form = new Form(); form.add("age", "28");
form.add("name", "Scott008");
form.add("subject", "English");
form.add("sex", "0");
form.add("id", "1"); String id = client.put(form.getWebRepresentation()).getText();
System.out.println("Teacher update " + id); } catch (Exception e) {
e.printStackTrace();
}
} public static void testDeleteTeacher(String url) {
ClientResource client = new ClientResource(url + "teacher/delete/1");
try {
System.out.println("Teacher delete " + client.delete().getText());
} catch (ResourceException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Client:

 package com.scott.restlet.client;

 public class Client {

     public static final String url = "http://localhost:8082/TestRestlet/";

     public static void main(String args[]){

         StudentOperateClient.testGetStudent(url);
StudentOperateClient.testUpdateStudent(url); TeacherOperateClient.testGetTeacher(url);
TeacherOperateClient.testUpdateTeacher(url);
}
}

2.7 运行

运行,得到如下结果:

服务端启动后:

2013-9-3 23:22:51 org.restlet.engine.http.connector.HttpServerHelper start
信息: Starting the internal HTTP server on port 8082
The restlet server started ...

客户端启动后的客户端信息:

2013-9-3 23:24:12 org.restlet.engine.http.connector.HttpClientHelper start
信息: Starting the default HTTP client
Student get {"id":1,"sex":0,"age":18,"name":"Scott","grade":3}
2013-9-3 23:24:12 org.restlet.engine.http.connector.HttpClientHelper start
信息: Starting the default HTTP client
Student update 1
2013-9-3 23:24:12 org.restlet.engine.http.connector.HttpClientHelper start
信息: Starting the default HTTP client
Teacher get {"id":1,"sex":1,"subject":"MATH","age":27,"name":"Toney"}
2013-9-3 23:24:12 org.restlet.engine.http.connector.HttpClientHelper start
信息: Starting the default HTTP client
Teacher update 1

客户端启动的服务端信息:

2013-9-3 23:22:51 org.restlet.engine.http.connector.HttpServerHelper start
信息: Starting the internal HTTP server on port 8082
The restlet server started ...
2013-9-3 23:24:12 org.restlet.engine.log.LogFilter afterHandle
信息: 2013-09-03 23:24:12 127.0.0.1 - - 8082 GET /TestRestlet/student/1/json - 200 - 0 70 http://localhost:8082 Restlet-Framework/2.0.6 -
2013-9-3 23:24:12 org.restlet.engine.log.LogFilter afterHandle
信息: 2013-09-03 23:24:12 127.0.0.1 - - 8082 PUT /TestRestlet/student/update - 200 1 39 4 http://localhost:8082 Restlet-Framework/2.0.6 -
2013-9-3 23:24:12 org.restlet.engine.log.LogFilter afterHandle
信息: 2013-09-03 23:24:12 127.0.0.1 - - 8082 GET /TestRestlet/teacher/1/json - 200 - 0 1 http://localhost:8082 Restlet-Framework/2.0.6 -
2013-9-3 23:24:13 org.restlet.engine.log.LogFilter afterHandle
信息: 2013-09-03 23:24:13 127.0.0.1 - - 8082 PUT /TestRestlet/teacher/update - 200 1 47 2 http://localhost:8082 Restlet-Framework/2.0.6 -

当然,此处的例子规模和功能都很小,是在参考了[2]的基础上稍加改造,算是可以作为学习RESTLET的第一步吧。

3 一些可参考的网址

[1]http://whui0110.iteye.com/blog/1682388

[2]http://www.infoq.com/cn/articles/rest-introduction

[3]http://www.lifeba.org/arch/restlet_develop_jax-rs_service_1.html

RESTLET开发实例的更多相关文章

  1. RESTLET开发实例(一)基于JAX-RS的REST服务

    RESTLET介绍 Restlet项目为“建立REST概念与Java类之间的映射”提供了一个轻量级而全面的框架.它可用于实现任何种类的REST式系统,而不仅仅是REST式Web服务. Restlet项 ...

  2. [转贴]JAVA:RESTLET开发实例(二)使用Component、Application的REST服务

    上一篇文章,我们介绍了基于JAX-RS的REST服务,本篇文章我们介绍不基于JAX-RS的模式.JAX-RS其实就是一个简单的 Application服务.和我们接下来介绍的Application基本 ...

  3. [转贴]JAVA :RESTLET开发实例(一)基于JAX-RS的REST服务

    RESTLET介绍 Restlet项目为“建立REST概念与Java类之间的映射”提供了一个轻量级而全面的框架.它可用于实现任何种类的REST式系统,而不仅仅是REST式Web服务. Restlet项 ...

  4. RESTLET开发实例(三)基于spring的REST服务

    http://www.lifeba.org/arch/restlet_spring_3.html 前面两篇文章,我们介绍了基于JAX-RS的REST服务以及Application的Rest服务.这里将 ...

  5. [转贴]JAVA:RESTLET开发实例(三)基于spring的REST服务

    前面两篇文章,我们介绍了基于JAX-RS的REST服务以及Application的Rest服务.这里将介绍restlet如何整合spring框架进行开发.Spring 是一个开源框架,是为了解决企业应 ...

  6. ecshop二次开发 给商品添加自定义字段【包含我自己进一步的开发实例详解】

    本文包含商品自定义添加教程及进一步的开发实例: 教程: 说起自定义字段,我想很多的朋友像我一样会想起一些开源的CMS(比如Dedecms.Phpcms.帝国)等,他们是可以在后台直接添加自定义字段的. ...

  7. RDIFramework.NET -.NET快速信息化系统开发整合框架 【开发实例 EasyUI】之产品管理(WebForm版)

    RDIFramework.NET—.NET快速开发整合框架 [开发实例]之产品管理(WebForm版) 接上篇:RDIFramework.NET (.NET快速信息化系统开发整合框架) [开发实例]之 ...

  8. RDIFramework.NET-.NET快速信息化系统开发整合框架 【开发实例 EasyUI】之产品管理(MVC版)

    RDIFramework.NET—.NET快速开发整合框架 [开发实例]之产品管理(MVC版) 接上篇:RDIFramework.NET (.NET快速信息化系统开发整合框架) [开发实例]之产品管理 ...

  9. Cocos2d-x 3.X手游开发实例详解

    Cocos2d-x 3.X手游开发实例详解(最新最简Cocos2d-x手机游戏开发学习方法,以热门游戏2048.卡牌为例,完整再现手游的开发过程,实例丰富,代码完备,Cocos2d-x作者之一林顺和泰 ...

随机推荐

  1. PAT-乙级-1008. 数组元素循环右移问题 (20)

    1008. 数组元素循环右移问题 (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 一个数组A中存有N(N>0)个整数,在不允 ...

  2. WP-Syntax 插件使用方法

    技术博客中使用WP-Syntax将代码高亮是最常见的.而一段时间不用总会忘记每种语言的的pre标签的值. 这里简单介绍下,WP-Syntax 是一个针对 Wordpress 的代码高亮插件,最大的优点 ...

  3. Nagios的安装配置与应用之五监控远程Linux服务器

    本文出自 “曹坏水” 博客,请务必保留此出处http://cao2012.blog.51cto.com/366908/1132113 NRPE是Nagios的一个功能扩展,它可在远程Linux和UNI ...

  4. Visual C++ unicode and utf8 转换

    ATL宏: USES_CONVERSION; W2A A2W CString StringUtil::UTF8_to_UNICODE(const char *utf8_string, int leng ...

  5. 跟随屏幕滚动层、遮罩层、获取Div相对定位、整个屏幕、html文档的jquery基本操作

    一.层跟随屏幕滚动 <div style="width:120px;height:120px;border:1px solid red; position:absolute; left ...

  6. CentOS 报no acceptable C compiler found in $PATH的解决办法

    CentOS 6.2下安装tcpreplay工具的时候,先安装libpcap-1.3.0,configure libpcap时出错. #./configure 提示没有GCC编译器环境) config ...

  7. CF 136B Ternary Logic

    http://codeforces.com/problemset/problem/136/B 题意 :就是说tor是一个三进制的运算,代表的是两个三进制数的运算,两个三进制数按位逐一相加后对三取余,没 ...

  8. linux 模拟延时和丢包

    这是 RHCA 中的一个 BDP 的测试,这也是公司很常用的一种延时和丢包的模拟,现在分享给大家. 我们做的应用软件,还有测试 TCP/UDP  对比,测试 BDP 对 TCP/IP 的影响时,我们都 ...

  9. APK签名校验绕过

    APK签名校验绕过 Android JNI 获取应用签名 android apk 防止反编译技术第一篇-加壳技术 android apk 防止反编译技术第五篇-完整性校验 利用IDA Pro反汇编程序 ...

  10. binary 和 varbinary

    固定长度或可变长度的 Binary 数据类型. binary [ ( n ) ] 长度为 n 字节的固定长度二进制数据,其中 n 是从 1 到 8,000 的值.存储大小为 n 字节. varbina ...