jersey是一种RestFul Webservice开发框架,作为JSR311的开源实现,替代了原有的基于SOAP的Web服务。jersey提供了更为简洁的API,提供了更为简洁的开发模式。
在实际应用中,将基于maven构建开发环境,主要其他工具包括:jersey1.8、Junit4、jersey-json。使用webservice访问实现对数据库的CRUD模拟操作。
pom.xml核心片段:
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> <version>1.8</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.8</version> </dependency> <!-- Json --> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-json</artifactId> <version>1.18</version> </dependency> <dependency> <groupId>com.owlike</groupId> <artifactId>genson</artifactId> <version>0.99</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>jsr311-api</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>asm</groupId> <artifactId>asm</artifactId> <version>3.2</version> </dependency> </dependencies>
编写Model类,用于传输数据,@XmlRootElement注解用于在以XML格式返回数据时,将Bean作为根节点:
package com.jersey.bean; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Student { private int id; private String name; private String dept; 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 String getDept() { return dept; } public void setDept(String dept) { this.dept = dept; } public Student(){} public Student(int id, String name, String dept) { super(); this.id = id; this.name = name; this.dept = dept; } }
使用jersey核心API构建WebService类。其中,list请求返回的数据格式是json,需要使用到genson的支持,这个工具可以将Java集合类绑定为特定的Json格式,从而使webservice访问请求响应json格式的数据。
package com.jersey.ws; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ws.rs.DELETE; import javax.ws.rs.FormParam; 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 javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.apache.log4j.Logger; import com.jersey.bean.Student; @Path("/students") public class RestWs { private static Logger logger = Logger.getLogger(RestWs.class); private static int index = 1; private static Map<Integer,Student> studentMap = new HashMap<Integer, Student>(); public RestWs(){ if(studentMap.size()==0){ studentMap.put(index, new Student(index++,"Askok","SC")); studentMap.put(index, new Student(index++,"Kloki","KONER")); } } @GET @Path("{studentid}") @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) public Student getData(@PathParam("studentid")int studentid){ if(studentMap.containsKey(studentid)){ return studentMap.get(studentid); }else{ return new Student(-1,"NULL","NULL"); } } @GET @Path("list") @Produces(MediaType.APPLICATION_JSON) public List<Student> getList(){ List<Student> list = new ArrayList<Student>(); list.addAll(studentMap.values()); return list; } @POST @Path("add") @Produces("text/plain") public String addStudent(@FormParam("name") String name, @FormParam("dept") String dept){ studentMap.put(index, new Student(index, name, dept)); return String.valueOf(index-1); } @DELETE @Path("delete/{studentid}") @Produces("text/plain") public String deleteStudent(@PathParam("studentid") int studentid){ logger.info("Delete student id at:"+studentid); Student del = studentMap.remove(studentid); if(del==null){ return "failed"; }else{ return "Student:"+del.getName()+"has been deleted"; } } @PUT @Path("put") @Produces("text/plain") public String putStudent(@QueryParam("studentid") int studentid, @QueryParam("name") String name, @QueryParam("dept") String dept){ logger.info("Add sudent, it's id:"+studentid); if(studentMap.containsKey(studentid)){ return "Can't add same student."; }else{ studentMap.put(studentid, new Student(studentid, name, dept)); } return "Student "+name+" has been added"; } }
注意,
修改web.xml文件:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>jerseyws</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name> <param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value> </init-param> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>com.jersey.ws</param-value> </init-param> <init-param> <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jerseyws</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app>
对GET和POST可以通过url访问及表单post提交进行测试。
对PUT和DELETE的客户端单元测试代码:
package test; import javax.ws.rs.core.MultivaluedMap; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.core.util.MultivaluedMapImpl; /** * @ClassName: TestPD * @Description: (这里用一句话描述这个类的作用) * @author hao1.yan * @date 2015年11月19日 下午3:25:58 */ @RunWith(BlockJUnit4ClassRunner.class) public class TestPD { private static final String BASE_URL = "http://localhost:8080/jersey/rest/students"; @Test public void testDelete(){ Client client = Client.create(); WebResource resource = client.resource(BASE_URL+"/delete/1"); ClientResponse response = resource.delete(ClientResponse.class); System.out.println("Response with a status of:"+response.getStatus()+","+response.getHeaders().toString()); } @Test public void testPut(){ Client client = Client.create(); WebResource resource = client.resource(BASE_URL+"/put"); MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl() ; queryParams.add("studentid", "4"); queryParams.add("name", "Klossd"); queryParams.add("dept", "newPL"); ClientResponse response = resource.queryParams(queryParams).put(ClientResponse.class,"foo:test"); System.out.println("Respone a status:"+response.getStatus()); } }
整个Webservice开发完成后,使用的基准URL是BASE_URL所定义的值,在访问其他资源时,只需要追加特定的路径和参数即可。