研究了两天CXF对restful的支持。
? 现在,想实现一个以
http://localhost:9999/roomservice 为入口,
http://localhost:9999/roomservice/room为房间列表,
http://localhost:9999/roomservice/room/001/ 为001号房间的信息,
http://localhost:9999/roomservice/room/001/person 为在001号房间主的人的列表
? 实现用HTTP请求对以上资源的CRUD。
? 首先建立room,person的POJO,这里只有一点需要注意:
- package?com.DAO;??
- ??
- import?javax.xml.bind.annotation.XmlRootElement;??
- ??
- @XmlRootElement(name="Person")??
- public?class?Person?{??
- ????private?String?name;??
- ????private?String?sex;??
- ????public?String?getName()?{??
- ????????return?name;??
- ????}??
- ????public?void?setName(String?name)?{??
- ????????this.name?=?name;??
- ????}??
- ????public?String?getSex()?{??
- ????????return?sex;??
- ????}??
- ????public?void?setSex(String?sex)?{??
- ????????this.sex?=?sex;??
- ????}??
- ??????
- }??
?
一定要在类的前边加上annotation ,这样才能让这个person的信息在POJO和XML之间转换。Room同理:
- import?java.util.Map;??
- ??
- import?javax.xml.bind.annotation.XmlRootElement;??
- ??
- @XmlRootElement(name="Room")??
- public?class?Room?{??
- ????public?Room()??
- ????{??
- ????????persons=new?HashMap<String,Person>();??
- ????}??
- ????String?id;??
- ????Map<String,Person>?persons;??
- ??????
- ????public?String?getId()?{??
- ????????return?id;??
- ????}??
- ????public?void?setId(String?id)?{??
- ????????this.id?=?id;??
- ????}??
- ????public?Map<String,?Person>?getPersons()?{??
- ????????return?persons;??
- ????}??
- ????public?void?setPersons(Map<String,?Person>?persons)?{??
- ????????this.persons?=?persons;??
- ????}??
- }??
POJO有了,接下来要写DAO,由于主要是为了学习restful,为了方便,不必要将数据持久化到数据库,而是存在一个静态的HashMap中:
- package?com.DAO;??
- ??
- import?java.util.HashMap;??
- import?java.util.Map;??
- ??
- public?class?RoomDAO?{??
- ????private?static?Map<String,?Room>?rooms;??
- ????static?{??
- ????????rooms?=?new?HashMap<String,?Room>();??
- ??????????
- ??????????
- ????????Person?p1=new?Person();??
- ????????p1.setName("Boris");??
- ????????p1.setSex("male");??
- ??????????
- ??????????
- ??????????
- ????????Room?r=new?Room();??
- ????????r.setId("001");??
- ????????r.getPersons().put(p1.getName(),?p1);??
- ????????rooms.put("001",?r);??
- ????}??
- ??
- ????public?static?void?addRoom(Room?room)?{??
- ????????rooms.put(room.getId(),?room);??
- ????}??
- ??
- ????public?static?void?deleteRoom(String?id)?{??
- ????????if?(rooms.containsKey(id))?{??
- ????????????rooms.remove(id);??
- ????????}??
- ??
- ????}??
- ??
- ????public?static?void?updateRoom(String?id,Room?room)?{??
- ????????rooms.remove(id);??
- ????????rooms.put(room.getId(),?room);??
- ????}??
- ??
- ????public?static?Room?getRoom(String?id)?{??
- ????????if?(rooms.containsKey(id))?{??
- ????????????return?rooms.get(id);??
- ????????}?else?{??
- ????????????return?null;??
- ????????}??
- ????}??
- ??????
- ????public?static?void?addPerson(String?id_room,Person?person)?{??
- ????????if(rooms.containsKey(id_room))??
- ????????{??
- ????????????Room?room=rooms.get(id_room);??
- ????????????room.getPersons().put(person.getName(),?person);??
- ????????}??
- ????}??
- ??????
- ????public?static?Rooms?getRooms()??
- ????{??
- ????????return?new?Rooms();??
- ????}??
- ??????
- ????public?static?void?deletePerson(String?id_room,String?name)??
- ????{??
- ????????if(rooms.containsKey(id_room))??
- ????????{??
- ????????????Room?room=rooms.get(id_room);??
- ????????????room.getPersons().remove(name);??
- ????????}??
- ????}??
- ??????
- ????public?static?Map<String,?Room>?getMapOfRooms()??
- ????{??
- ????????return?rooms;??
- ????}??
- }??
接下来是重点,如果想发布restful webservice,要通过一个叫JAXRSServerFactoryBean的类来发布。这个类有几个方法是要了解的:
public void setResourceClasses(Class... classes);
那一系列的Class类型的参数,是告诉这个类,发布服务时,会用到的POJO(就像上边写的Room,Person)。
public void setAddress(String address);
这个方法是告诉这个类,服务的地址,比如"http://localhost:9999"
public void setServiceBeans(Object... beans)
这里是重点,这个方法,要给这个用来发布服务的类一个Service bean.这个Bean是我们要手动编写的,作用是告诉服务,收到什么样的请求,应该怎么样处理。
现在,先来编写这个Service bean:
- package?com.server;??
- ??
- import?javax.ws.rs.Consumes;??
- 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?com.DAO.Person;??
- import?com.DAO.Room;??
- import?com.DAO.RoomDAO;??
- import?com.DAO.Rooms;??
- ??
- @Path("/roomservice")??
- @Produces("application/xml")??
- public?class?RoomService?{??
- ??????
- ????@GET??
- ????@Path("/room/{id}")??
- ????@Consumes("application/xml")??
- ????public?Room?getRoom(@PathParam("id")String?id?)??
- ????{??
- ????????System.out.println("get?room?by?id=?"+id);??
- ????????Room?room=RoomDAO.getRoom(id);??
- ????????return?room;??
- ????}??
- ????@GET??
- ????@Path("/room")??
- ????@Consumes("application/xml")??
- ????public?Rooms?getAllRoom()??
- ????{??
- ????????System.out.println("get?all?room");??
- ????????Rooms?rooms=RoomDAO.getRooms();??
- ????????return?rooms;??
- ????}??
- ??????
- ????@POST??
- ????@Path("/room")??
- ????@Consumes("application/xml")??
- ????public?void?addRoom(Room?room)??
- ????{??
- ????????System.out.println("add?room?which?id?is:"+room.getId());??
- ????????RoomDAO.addRoom(room);??
- ????}??
- ????@PUT??
- ????@Path("/room/{id}")??
- ????@Consumes("application/xml")??
- ????public?void?updateRoom(@PathParam("id")String?id,Room?room)??
- ????{??
- ????????System.out.println("update?room?which?original?id?is:"+room.getId());??
- ????????RoomDAO.updateRoom(id,room);??
- ????}??
- ????@DELETE??
- ????@Path("/room/{id}")??
- ????@Consumes("application/xml")??
- ????public?void?deleteRoom(@PathParam("id")String?id)??
- ????{??
- ????????System.out.println("remove?room?by?id=?"+id);??
- ????????RoomDAO.deleteRoom(id);??
- ????}??
- ????@POST??
- ????@Path("/room/{id}")??
- ????@Consumes("application/xml")??
- ????public?void?addPerson(@PathParam("id")?String?id,Person?person)??
- ????{??
- ????????System.out.println("add?person?who's?name?is:"+person.getName());??
- ????????RoomDAO.addPerson(id,?person);??
- ????}??
- ????@DELETE??
- ????@Path("/room/{id}/{name}")??
- ????@Consumes("application/xml")??
- ????public?void?deletePerson(@PathParam("id")String?id,@PathParam("name")String?name)??
- ????{??
- ????????System.out.println("remove?person?who's?name?is:?"+name);??
- ????????RoomDAO.deletePerson(id,?name);??
- ????}??
- }??
需要注意:每个方法之前,要用annotation声明http请求的method类型,比如GET,DELETE,POST,PUT.
@Produces("application/xml")我还没弄清楚到底是声明的接受格式还是返回格式,还是其他。
@Path("/room/{id}")中的id是一个参数,应该在方法的参数列表中声明:
public void deletePerson(@PathParam("id")String id,@PathParam("name")String name)
这样就能得到URL中的id了。
现在,这些房间被资源化了,id为001的房间被资源化为一个URL,那地址应该是
http:{服务器地址}:{端口}/roomservice/rrom/001??
现在,创建一个Server:
- package?com.server;??
- ??
- import?org.apache.cxf.jaxrs.JAXRSServerFactoryBean;??
- ??
- import?com.DAO.Person;??
- import?com.DAO.Room;??
- import?com.DAO.Rooms;??
- ??
- public?class?Server?{??
- ??
- ????public?static?void?main(String[]?args)?{??
- ????????RoomService?service?=?new?RoomService();??
- ??
- ??????????
- ????????JAXRSServerFactoryBean?restServer?=?new?JAXRSServerFactoryBean();??
- ????????restServer.setResourceClasses(Room.class,Person.class,Rooms.class);??
- ????????restServer.setServiceBeans(service);??
- ????????restServer.setAddress("http://localhost:9999/");??
- ????????restServer.create();??
- ????}??
- }??
现在,服务已经发布成功了,在浏览器输入http://localhost:9999/roomservice/room/001? 得到结果:
- <room>??
- <id>001</id>??
- ???
- <persons>??
- ???
- <entry>??
- <key>Boris</key>??
- ???
- <value>??
- <name>Boris</name>??
- <sex>male</sex>??
- </value>??
- </entry>??
- </persons>??
- </room>??
如果用浏览器去访问,发送的http请求只能所GET,因此如果想对数据进行操作,必须写一个客户端。
在写客户端之前,有一个问题:
在浏览器输入http://localhost:9999/roomservice/room/
什么都看不到,可是,我想要得到房间列表。但是,cxf发布restful只认你给他的类的class。所以你想让服务器返回一个room的列表给客户端,是不行的。所以,必须想别的办法,我是又写了一个POJO,这个POJO里只有一个属性,就是一个存放所有room的Map:
package com.DAO;
- import?java.util.Map;??
- ??
- import?javax.xml.bind.annotation.XmlRootElement;??
- @XmlRootElement(name="rooms")??
- public?class?Rooms?{??
- ????Map<String,Room>?rooms;??
- ????public?Rooms()??
- ????{??
- ????????rooms=RoomDAO.getMapOfRooms();??
- ????}??
- ????public?Map<String,?Room>?getRooms()?{??
- ????????return?rooms;??
- ????}??
- ????public?void?setRooms(Map<String,?Room>?rooms)?{??
- ????????this.rooms?=?rooms;??
- ????}??
- }??
这样,然后再把DAO的方法加上:
- @GET??
- ????@Path("/room")??
- ????@Consumes("application/xml")??
- ????public?Rooms?getAllRoom()??
- ????{??
- ????????System.out.println("get?all?room");??
- ????????Rooms?rooms=RoomDAO.getRooms();??
- ????????return?rooms;??
- ????}??
这样就能以list的形式显示出所有room了。
访问http://localhost:9999/roomservice/room/
结果如下:
- <rooms>??
- ???
- <rooms>??
- ???
- <entry>??
- <key>006</key>??
- ???
- <value>??
- <id>006</id>??
- <persons/>??
- </value>??
- </entry>??
- ???
- <entry>??
- <key>001</key>??
- ???
- <value>??
- <id>001</id>??
- ???
- <persons>??
- ???
- <entry>??
- <key>Boris</key>??
- ???
- <value>??
- <name>Boris</name>??
- <sex>male</sex>??
- </value>??
- </entry>??
- </persons>??
- </value>??
- </entry>??
- </rooms>??
- </rooms>??
关于客户端
http://sunbo1591.iteye.com/blog/766029