Creating a simple web service with Restlet
Posted by Philippe Van Nuijs at 16:12Restlet是一个轻权的RESt框架。遗憾的是没有很好的示例来描述如何使用它。虽然示例代码包里有一些,但是都比较初级,没有涉及如何创建一个完整的REST web service示例(使用create,update,delete功能)。
这里并没有真正的执行数据库操作,你可以再Todo部分填充自己的数据访问代码:
首先,创建一个简单的User类,包含ID和name两个变量:
import java.nio.Buffer;
import org.json.JSONObject;
public class User {
private String id = null;
private String name = null;
/**
* @return Returns the id.
*/
public String getId() {
return id;
}
/**
* @param id
* The id to set.
*/
public void setId(String id) {
this.id = id;
}
/**
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* @param name
* The name to set.
*/
public void setName(String name) {
this.name = name;
}
/**
* Convert this object to a JSON object for representation
*/
public JSONObject toJSON() {
try{
JSONObject jsonobj = new JSONObject();
jsonobj.put("id", this.id);
jsonobj.put("name", this.name);
return jsonobj;
}catch(Exception e){
return null;
}
}
/**
* Convert this object to a string for representation
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("id:");
sb.append(this.id);
sb.append(",name:");
sb.append(this.name);
return sb.toString();
}
}
创建错误展示消息类,用来传递错误信息:
import org.json.JSONObject;
public class ErrorMessage {
public JSONObject toJSON() {
JSONObject jsonobj = new JSONObject();
try {
jsonobj.put("error", "An error occured");
return jsonobj;
} catch (Exception e) {
return null;
}
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("error:");
sb.append("An error occured");
return sb.toString();
}
}
Now, let's create our UserResource.
好了,现在创建用户资源 UserResource类。
And implement a restlet server, listening on port 8100.
import org.restlet.Context;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.ResourceException;
import org.restlet.resource.StringRepresentation;
import org.restlet.resource.Variant;
public class UserResource extends Resource {
private User user = null;
public UserResource(Context context, Request request, Response response) {
super(context, request, response);
String userid = null;
userid = (String) getRequest().getAttributes().get("id");
this.user = findUser(userid);
getVariants().add(new Variant(MediaType.TEXT_PLAIN));
getVariants().add(new Variant(MediaType.APPLICATION_JSON));
}
/**
* Allow a PUT http request
*
* @return
*/
public boolean allowPut() {
return true;
}
/**
* Allow a POST http request
*
* @return
*/
public boolean allowPost() {
return true;
}
/**
* Allow a DELETE http request
*
* @return
*/
public boolean allowDelete() {
return true;
}
/**
* Allow the resource to be modified
*
* @return
*/
public boolean setModifiable() {
return true;
}
/**
* Allow the resource to be read
*
* @return
*/
public boolean setReadable() {
return true;
}
/**
* Find the requested user object
*
* @param userid
* @return
*/
private User findUser(String userid) {
try {
if (null == userid)
return null;
// :TODO {do some database lookup here }
// user = result of lookup
// This part should be replaced by a lookup
User u = new User();
u.setId("1");
u.setName("name");
// end replace
return u;
} catch (Exception e) {
return null;
}
}
/**
* Represent the user object in the requested format.
*
* @param variant
* @return
* @throws ResourceException
*/
public Representation represent(Variant variant) throws ResourceException {
Representation result = null;
if (null == this.user) {
ErrorMessage em = new ErrorMessage();
return representError(variant, em);
} else {
if (variant.getMediaType().equals(MediaType.APPLICATION_JSON)) {
result = new JsonRepresentation(this.user.toJSON());
} else {
result = new StringRepresentation(this.user.toString());
}
}
return result;
}
/**
* Handle a POST Http request. Create a new user
*
* @param entity
* @throws ResourceException
*/
public void acceptRepresentation(Representation entity)
throws ResourceException {
// We handle only a form request in this example. Other types could be
// JSON or XML.
try {
if (entity.getMediaType().equals(MediaType.APPLICATION_WWW_FORM,
true)) {
Form form = new Form(entity);
User u = new User();
u.setName(form.getFirstValue("user[name]"));
// :TODO {save the new user to the database}
getResponse().setStatus(Status.SUCCESS_OK);
// We are setting the representation in the example always to
// JSON.
// You could support multiple representation by using a
// parameter
// in the request like "?response_format=xml"
Representation rep = new JsonRepresentation(u.toJSON());
getResponse().setEntity(rep);
} else {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
}
} catch (Exception e) {
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
}
}
/**
* Handle a PUT Http request. Update an existing user
*
* @param entity
* @throws ResourceException
*/
public void storeRepresentation(Representation entity)
throws ResourceException {
try {
if (null == this.user) {
ErrorMessage em = new ErrorMessage();
Representation rep = representError(entity.getMediaType(), em);
getResponse().setEntity(rep);
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return;
}
if (entity.getMediaType().equals(MediaType.APPLICATION_WWW_FORM,
true)) {
Form form = new Form(entity);
this.user.setName(form.getFirstValue("user[name]"));
// :TODO {update the new user in the database}
getResponse().setStatus(Status.SUCCESS_OK);
// We are setting the representation in this example always to
// JSON.
// You could support multiple representation by using a
// parameter
// in the request like "?response_format=xml"
Representation rep = new JsonRepresentation(this.user.toJSON());
getResponse().setEntity(rep);
} else {
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
}
} catch (Exception e) {
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
}
}
/**
* Handle a DELETE Http Request. Delete an existing user
*
* @param entity
* @throws ResourceException
*/
public void removeRepresentations()
throws ResourceException {
try {
if (null == this.user) {
ErrorMessage em = new ErrorMessage();
Representation rep = representError(MediaType.APPLICATION_JSON, em);
getResponse().setEntity(rep);
getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
return;
}
// :TODO {delete the user from the database}
getResponse().setStatus(Status.SUCCESS_OK);
} catch (Exception e) {
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
}
}
/**
* Represent an error message in the requested format.
*
* @param variant
* @param em
* @return
* @throws ResourceException
*/
private Representation representError(Variant variant, ErrorMessage em)
throws ResourceException {
Representation result = null;
if (variant.getMediaType().equals(MediaType.APPLICATION_JSON)) {
result = new JsonRepresentation(em.toJSON());
} else {
result = new StringRepresentation(em.toString());
}
return result;
}
protected Representation representError(MediaType type, ErrorMessage em)
throws ResourceException {
Representation result = null;
if (type.equals(MediaType.APPLICATION_JSON)) {
result = new JsonRepresentation(em.toJSON());
} else {
result = new StringRepresentation(em.toString());
}
return result;
}
}
And implement a restlet server, listening on port 8100.
同时,我们事先一个restlet 服务器,监听8100端口:
You can test the restlet web service with any internet browser except for the PUT and DELETE requests. I prefer curl to test a Restful web service.
import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.Router;
import org.restlet.data.MediaType;
import org.restlet.data.Protocol;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.StringRepresentation;
public class WebServiceApplication extends Application {
public static void main(String[] args) throws Exception {
// Create a component
Component component = new Component();
component.getServers().add(Protocol.HTTP, 8100);
WebServiceApplication application = new WebServiceApplication(
component.getContext());
// Attach the application to the component and start it
component.getDefaultHost().attach(application);
component.start();
}
public WebServiceApplication() {
super();
}
public WebServiceApplication(Context context) {
super(context);
}
@Override
public Restlet createRoot() {
Router router = new Router(getContext());
router.attach("/users", UserResource.class);
router.attach("/users/{id}", UserResource.class);
Restlet mainpage = new Restlet() {
@Override
public void handle(Request request, Response response) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<html>");
stringBuilder
.append("<head><title>Sample Application Servlet Page</title></head>");
stringBuilder.append("<body bgcolor=white>");
stringBuilder.append("<table border=\"0\">");
stringBuilder.append("<tr>");
stringBuilder.append("<td>");
stringBuilder.append("<h1>2048Bits.com example - REST</h1>");
stringBuilder.append("</td>");
stringBuilder.append("</tr>");
stringBuilder.append("</table>");
stringBuilder.append("</body>");
stringBuilder.append("</html>");
response.setEntity(new StringRepresentation(stringBuilder
.toString(), MediaType.TEXT_HTML));
}
};
router.attach("", mainpage);
return router;
}
}
You can test the restlet web service with any internet browser except for the PUT and DELETE requests. I prefer curl to test a Restful web service.
你可以使用任何浏览器测试restlet web service的服务(出了PUT和DELETE请求)。最好使用curl来测试,具体方法如下:
GET REQUEST - Show the information of a user:
POST REQUEST - Create a new user:
PUT REQUEST - Update an existing user:
DELETE REQUEST - Delete an existing user:
GET REQUEST - Show the information of a user:
curl http://localhost:8100/users/1
POST REQUEST - Create a new user:
curl -d "user[name]=John" http://localhost:8100/users
PUT REQUEST - Update an existing user:
curl -X PUT -d "user[name]=Jane" http://localhost:8100/users/1
DELETE REQUEST - Delete an existing user:
curl -X DELETE http://localhost:8100/users/1