研究了兩天CXF對(duì)restful的支持。
現(xiàn)在,想實(shí)現(xiàn)一個(gè)以
http://localhost:9999/roomservice 為入口,
http://localhost:9999/roomservice/room為房間列表,
http://localhost:9999/roomservice/room/001/ 為001號(hào)房間的信息,
http://localhost:9999/roomservice/room/001/person 為在001號(hào)房間主的人的列表
實(shí)現(xiàn)用HTTP請(qǐng)求對(duì)以上資源的CRUD。
首先建立room,person的POJO,這里只有一點(diǎn)需要注意:
- 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;
- }
-
- }
一定要在類(lèi)的前邊加上annotation ,這樣才能讓這個(gè)person的信息在POJO和XML之間轉(zhuǎn)換。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有了,接下來(lái)要寫(xiě)DAO,由于主要是為了學(xué)習(xí)restful,為了方便,不必要將數(shù)據(jù)持久化到數(shù)據(jù)庫(kù),而是存在一個(gè)靜態(tài)的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;
- }
- }
接下來(lái)是重點(diǎn),如果想發(fā)布restful webservice,要通過(guò)一個(gè)叫JAXRSServerFactoryBean的類(lèi)來(lái)發(fā)布。這個(gè)類(lèi)有幾個(gè)方法是要了解的:
public void setResourceClasses(Class... classes);
那一系列的Class類(lèi)型的參數(shù),是告訴這個(gè)類(lèi),發(fā)布服務(wù)時(shí),會(huì)用到的POJO(就像上邊寫(xiě)的Room,Person)。
public void setAddress(String address);
這個(gè)方法是告訴這個(gè)類(lèi),服務(wù)的地址,比如"http://localhost:9999"
public void setServiceBeans(Object... beans)
這里是重點(diǎn),這個(gè)方法,要給這個(gè)用來(lái)發(fā)布服務(wù)的類(lèi)一個(gè)Service bean.這個(gè)Bean是我們要手動(dòng)編寫(xiě)的,作用是告訴服務(wù),收到什么樣的請(qǐng)求,應(yīng)該怎么樣處理。
現(xiàn)在,先來(lái)編寫(xiě)這個(gè)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);
- }
- }
需要注意:每個(gè)方法之前,要用annotation聲明http請(qǐng)求的method類(lèi)型,比如GET,DELETE,POST, PUT.
@Produces("application/xml")我還沒(méi)弄清楚到底是聲明的接受格式還是返回格式,還是其他。
@Path("/room/{id}")中的id是一個(gè)參數(shù),應(yīng)該在方法的參數(shù)列表中聲明:
public void deletePerson(@PathParam("id")String id,@PathParam("name")String name)
這樣就能得到URL中的id了。
現(xiàn)在,這些房間被資源化了,id為001的房間被資源化為一個(gè)URL,那地址應(yīng)該是
http:{服務(wù)器地址}:{端口}/roomservice/rrom/001
現(xiàn)在,創(chuàng)建一個(gè)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();
- }
- }
現(xiàn)在,服務(wù)已經(jīng)發(fā)布成功了,在瀏覽器輸入http://localhost:9999/roomservice/room/001 得到結(jié)果:
- <room>
- <id>001</id>
-
- <persons>
-
- <entry>
- <key>Boris</key>
-
- <value>
- <name>Boris</name>
- <sex>male</sex>
- </value>
- </entry>
- </persons>
- </room>
如果用瀏覽器去訪問(wèn),發(fā)送的http請(qǐng)求只能所GET,因此如果想對(duì)數(shù)據(jù)進(jìn)行操作,必須寫(xiě)一個(gè)客戶(hù)端。
在寫(xiě)客戶(hù)端之前,有一個(gè)問(wèn)題:
在瀏覽器輸入http://localhost:9999/roomservice/room/
什么都看不到,可是,我想要得到房間列表。但是,cxf發(fā)布restful只認(rèn)你給他的類(lèi)的class。所以你想讓服務(wù)器返回一個(gè)room的列表給客戶(hù)端,是不行的。所以,必須想別的辦法,我是又寫(xiě)了一個(gè)POJO,這個(gè)POJO里只有一個(gè)屬性,就是一個(gè)存放所有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了。
訪問(wèn)http://localhost:9999/roomservice/room/
結(jié)果如下:
- <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>
關(guān)于客戶(hù)端
http://sunbo1591./blog/766029