Spring Rest
2012-12-04 19:19
381 查看
Spring整合CXF,发布RSETful风格WebService
这篇文章是承接之前CXF整合Spring的这个项目示例的延伸,所以有很大一部分都是一样的。关于发布CXFWebServer和Spring整合CXF这里就不再多加赘述了。如果你对Spring整合CXFWebService不了解,具体你可以参看这两篇文章:如果你不了解restful风格的WebService,你可以参考:
SpringMVC对RESTful的支持:
使用Jersey框架,搭建RESTfulWebService(这个也比较简单)
官方文档:
其中,比较常用的RESTful框架就有Jersey、SpringREST、CXFRESTful,这些都可以很好的整合Spring框架,发布也相当的简单。且简单、易用、易上手,文档也比较丰富。
开发环境:
System:Windows
JavaEEServer:tomcat6
JavaSDK:jdk6+
IDE:eclipse、MyEclipse6.6
开发依赖库:
JDK6、JavaEE5、CXF-2.3.3、Spring3.0.4
Email:
Blog:
下面我们就接着
准备工作
首先,你需要添加相关的jar包
其中,jsr331-api-1.1.1.jar是必须的,利用CXF发布REST服务得用到它,在cxf的lib库中可以找到这个jar。
下载地址:
其它的jar包都是非必须的!
JavaEntity
packagecom.hoo.entity;
importjava.util.Map;
importjavax.xml.bind.annotation.XmlRootElement;
/**
*<b>function:</b>MapBean封装Map集合元素
*@authorhoojo
*@createDate2012-7-20下午01:22:31
*@fileMapBean.java
*@packagecom.hoo.entity
*@projectCXFWebService
*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code] *@emailhoojo_@126.com*@version1.0*/@XmlRootElementpublicclassMapBean{privateMap<String,User>map;//@XmlElement(type=User.class)publicMap<String,User>getMap(){returnmap;}publicvoidsetMap(Map<String,User>map){this.map=map;}}packagecom.hoo.entity;importjava.util.HashMap;importjava.util.List;importjavax.xml.bind.annotation.XmlRootElement;/***<b>function:</b>UsersEntity*@authorhoojo*@createDate2011-3-18上午09:27:31*@fileUsers.java*@packagecom.hoo.entity*@projectCXFWebService*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code] *@emailhoojo_@126.com*@version1.0*/@XmlRootElement(name="UserInfos")publicclassUsers{privateList<User>users;privateUser[]userArr;privateHashMap<String,User>maps;//getter/setter}packagecom.hoo.entity;importjava.io.Serializable;importjavax.xml.bind.annotation.XmlRootElement;/***<b>function:</b>UserEntity*@authorhoojo*@createDateDec16,201010:20:02PM*@fileUser.java*@packagecom.hoo.entity*@projectAxisWebService*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code] *@emailhoojo_@126.com*@version1.0*/@XmlRootElement(name="UserInfo")publicclassUserimplementsSerializable{privatestaticfinallongserialVersionUID=677484458789332877L;privateintid;privateStringname;privateStringemail;privateStringaddress;//getter/setter@OverridepublicStringtoString(){returnthis.id+"#"+this.name+"#"+this.email+"#"+this.address;}}
一、定义你的WebService的接口RESTSample.java,代码如下packagecom.hoo.service;importjava.io.IOException;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjavax.ws.rs.Consumes;importjavax.ws.rs.DELETE;importjavax.ws.rs.GET;importjavax.ws.rs.POST;importjavax.ws.rs.PUT;importjavax.ws.rs.Path;importjavax.ws.rs.PathParam;importjavax.ws.rs.Produces;importjavax.ws.rs.core.Context;importjavax.ws.rs.core.MediaType;importcom.hoo.entity.MapBean;importcom.hoo.entity.User;importcom.hoo.entity.Users;/*注释(Annotation):在javax.ws.rs.*中定义,是JAX-RS(JSR311)规范的一部分。@Path:定义资源基URI。由上下文根和主机名组成,资源标识符类似于http://localhost:8080/RESTful/rest/hello。 @GET:这意味着以下方法可以响应HTTPGET方法。@Produces:以纯文本方式定义响应内容MIME类型。@Context:使用该注释注入上下文对象,比如Request、Response、UriInfo、ServletContext等。@Path("{contact}"):这是@Path注释,与根路径“/contacts”结合形成子资源的URI。@PathParam("contact"):该注释将参数注入方法参数的路径,在本例中就是联系人id。其他可用的注释有@FormParam、@QueryParam等。@Produces:响应支持多个MIME类型。在本例和上一个示例中,APPLICATION/XML将是默认的MIME类型。*//***<b>function:</b>CXFRESTful风格WebService*@authorhoojo*@createDate2012-7-20下午01:23:04*@fileRESTSampleSource.java*@packagecom.hoo.service*@projectCXFWebService*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code] *@emailhoojo_@126.com*@version1.0*/@Path(value="/sample")publicinterfaceRESTSample{@GET@Produces(MediaType.TEXT_PLAIN)publicStringdoGet();@GET@Produces(MediaType.TEXT_PLAIN)@Path("/request/{param}")publicStringdoRequest(@PathParam("param")Stringparam,@ContextHttpServletRequestservletRequest,@ContextHttpServletResponseservletResponse);@GET@Path("/bean/{id}")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicUsergetBean(@PathParam("id")intid);@GET@Path("/list")@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicUsersgetList();@GET@Path("/map")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicMapBeangetMap();/*@Consumes:声明该方法使用HTMLFORM。@FormParam:注入该方法的HTML属性确定的表单输入。@Response.created(uri).build():构建新的URI用于新创建的联系人(/contacts/{id})并设置响应代码(201/created)。您可以使用http://localhost:8080/Jersey/rest/contacts/<id>访问新联系人 */@POST@Path("/postData")publicUserpostData(Useruser)throwsIOException;@PUT@Path("/putData/{id}")@Consumes(MediaType.APPLICATION_XML)publicUserputData(@PathParam("id")intid,Useruser);@DELETE@Path("/removeData/{id}")publicvoiddeleteData(@PathParam("id")intid);}
二、RESTSample接口的实现,这里我们只是简单的实现下,并不是涉及实际的具体业务packagecom.hoo.service;importjava.io.IOException;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjavax.ws.rs.DELETE;importjavax.ws.rs.GET;importjavax.ws.rs.POST;importjavax.ws.rs.PUT;importjavax.ws.rs.Path;importjavax.ws.rs.PathParam;importjavax.ws.rs.Produces;importjavax.ws.rs.core.Context;importjavax.ws.rs.core.MediaType;importjavax.ws.rs.core.Request;importjavax.ws.rs.core.UriInfo;importcom.hoo.entity.MapBean;importcom.hoo.entity.User;importcom.hoo.entity.Users;/*注释(Annotation):在javax.ws.rs.*中定义,是JAX-RS(JSR311)规范的一部分。@Path:定义资源基URI。由上下文根和主机名组成,资源标识符类似于http://localhost:8080/RESTful/rest/hello。 @GET:这意味着以下方法可以响应HTTPGET方法。@Produces:以纯文本方式定义响应内容MIME类型。@Context:使用该注释注入上下文对象,比如Request、Response、UriInfo、ServletContext等。@Path("{contact}"):这是@Path注释,与根路径“/contacts”结合形成子资源的URI。@PathParam("contact"):该注释将参数注入方法参数的路径,在本例中就是联系人id。其他可用的注释有@FormParam、@QueryParam等。@Produces:响应支持多个MIME类型。在本例和上一个示例中,APPLICATION/XML将是默认的MIME类型。*//***<b>function:</b>CXFRESTful风格WebService*@authorhoojo*@createDate2012-7-20下午01:23:04*@fileRESTSampleSource.java*@packagecom.hoo.service*@projectCXFWebService*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code] *@emailhoojo_@126.com*@version1.0*/@Path(value="/sample")publicclassRESTSampleSourceimplementsRESTSample{@ContextprivateUriInfouriInfo;@ContextprivateRequestrequest;@GET@Produces(MediaType.TEXT_PLAIN)publicStringdoGet(){return"thisisgetrestrequest";}@GET@Produces(MediaType.TEXT_PLAIN)@Path("/request/{param}")publicStringdoRequest(@PathParam("param")Stringparam,@ContextHttpServletRequestservletRequest,@ContextHttpServletResponseservletResponse){System.out.println(servletRequest);System.out.println(servletResponse);System.out.println(servletRequest.getParameter("param"));System.out.println(servletRequest.getContentType());System.out.println(servletResponse.getCharacterEncoding());System.out.println(servletResponse.getContentType());return"success";}@GET@Path("/bean/{id}")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicUsergetBean(@PathParam("id")intid){System.out.println("####getBean#####");System.out.println("id:"+id);System.out.println("Method:"+request.getMethod());System.out.println("uri:"+uriInfo.getPath());System.out.println(uriInfo.getPathParameters());Useruser=newUser();user.setId(id);user.setName("JojO");returnuser;}@GET@Path("/list")@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})publicUsersgetList(){System.out.println("####getList#####");System.out.println("Method:"+request.getMethod());System.out.println("uri:"+uriInfo.getPath());System.out.println(uriInfo.getPathParameters());List<User>list=newArrayList<User>();Useruser=null;for(inti=0;i<4;i++){user=newUser();user.setId(i);user.setName("JojO-"+i);list.add(user);}Usersusers=newUsers();users.setUsers(list);returnusers;}@GET@Path("/map")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicMapBeangetMap(){System.out.println("####getMap#####");System.out.println("Method:"+request.getMethod());System.out.println("uri:"+uriInfo.getPath());System.out.println(uriInfo.getPathParameters());Map<String,User>map=newHashMap<String,User>();Useruser=null;for(inti=0;i<4;i++){user=newUser();user.setId(i);user.setName("JojO-"+i);map.put("key-"+i,user);}MapBeanbean=newMapBean();bean.setMap(map);returnbean;}/*@Consumes:声明该方法使用HTMLFORM。@FormParam:注入该方法的HTML属性确定的表单输入。@Response.created(uri).build():构建新的URI用于新创建的联系人(/contacts/{id})并设置响应代码(201/created)。您可以使用http://localhost:8080/Jersey/rest/contacts/<id>访问新联系人 */@POST@Path("/postData")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicUserpostData(Useruser)throwsIOException{System.out.println(user);user.setName("jojo##12321321");returnuser;}@PUT@Path("/putData/{id}")@Produces({MediaType.APPLICATION_XML})publicUserputData(@PathParam("id")intid,Useruser){System.out.println("#####putData#####");System.out.println(user);user.setId(id);user.setAddress("hoojo#gz");user.setEmail("hoojo_@126.com");user.setName("hoojo");System.out.println(user);returnuser;}@DELETE@Path("/removeData/{id}")publicvoiddeleteData(@PathParam("id")intid){System.out.println("#######deleteData#######"+id);}}
三、配置我们的WebService,修改applicationContext-server.xml。这里主要是添加jaxrs标签的支持,修改头部文件如下:<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:jaxrs="http://cxf.apache.org/jaxrs"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans'target='_blank'>http://www.springframework.org/schema/beans/spring-beans-3.0.xsd[/code] 'target='_blank'>http://www.springframework.org/schema/context[/code] 'target='_blank'>http://www.springframework.org/schema/context/spring-context-3.0.xsd[/code] http://cxf.apache.org/jaxws 'target='_blank'>http://cxf.apache.org/schemas/jaxws.xsd[/code] http://cxf.apache.org/jaxrshttp://cxf.apache.org/schemas/jaxrs.xsd">
特别注意上面加粗带下划线的部分,这是新增加的配置。我们发布restfulWebService需要用到它。
然后在配置文件中添加如下配置<importresource="classpath:META-INF/cxf/cxf.xml"/><importresource="classpath:META-INF/cxf/cxf-extension-soap.xml"/><importresource="classpath:META-INF/cxf/cxf-servlet.xml"/><beanid="restSample"class="com.hoo.service.RESTSampleSource"/><!--这里的地址很重要,客户端需要通过这个地址来访问WebService--><jaxrs:serverid="restServiceContainer"address="/rest"><jaxrs:serviceBeans><refbean="restSample"/></jaxrs:serviceBeans><jaxrs:extensionMappings><entrykey="json"value="application/json"/><entrykey="xml"value="application/xml"/></jaxrs:extensionMappings><jaxrs:languageMappings><entrykey="en"value="en-gb"/></jaxrs:languageMappings></jaxrs:server>
这样服务器端就完成了CXFRESTfulWebService的发布,启动你的tomcat。然后在浏览器中服务地址:http://localhost:8000/CXFWebService/(其实这里请求的是CXFServlet,你可以看看上一篇Spring整合CXF文章的web.xml的配置)
你就可以看到我们这里刚刚发布的RESTSamplerest的WebService
你也可以看看里面的xml,也就是WebService的wsdl文件内容。我们找一个GET方式的WebService的方法,在浏览器中调用一下试试http://localhost:8000/CXFWebService/rest/sample/bean/123
这个url对应到下面这个方法@GET@Path("/bean/{id}")@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})publicUsergetBean(@PathParam("id")intid)
结果如下
一篇xml文档内容。
四、编写客户端代码,调用RESTfulWebServicepackagecom.hoo.client;importjava.io.IOException;importjavax.ws.rs.core.MediaType;importorg.apache.cxf.jaxrs.client.WebClient;importorg.junit.After;importorg.junit.Before;importorg.junit.Test;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;importcom.hoo.entity.MapBean;importcom.hoo.entity.User;importcom.hoo.entity.Users;importcom.hoo.service.RESTSample;/***<b>function:</b>RESTful风格WebService*@authorhoojo*@createDate2012-7-20下午03:31:03*@fileRSETServiceClient.java*@packagecom.hoo.client*@projectCXFWebService*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code] *@emailhoojo_@126.com*@version1.0*/publicclassRSETServiceClient{privatestaticWebClientclient;@Beforepublicvoidinit(){//手动创建webClient对象,注意这里的地址是发布的那个/rest地址//Stringurl="http://localhost:8000/CXFWebService/rest/";//client=WebClient.create(url);//从SpringIoc容器中拿webClient对象ApplicationContextctx=newClassPathXmlApplicationContext("applicationContext-client.xml");client=ctx.getBean("webClient",WebClient.class);}@Afterpublicvoiddestory(){}@TestpublicvoidtestGet(){System.out.println(client.path("sample").accept(MediaType.TEXT_PLAIN).get(String.class));}@TestpublicvoidtestRequest(){System.out.println(client.path("sample/request/234234").accept(MediaType.TEXT_PLAIN).get(String.class));}@TestpublicvoidtestBean(){Useruser=client.path("sample/bean/{id}",25).accept(MediaType.APPLICATION_XML).get(User.class);System.out.println(user);}@TestpublicvoidtestList(){System.out.println(client.path("sample/list").accept(MediaType.APPLICATION_XML).get(Users.class).getUsers());}@TestpublicvoidtestMap(){System.out.println(client.path("sample/map").accept(MediaType.APPLICATION_XML).get(MapBean.class).getMap());}@TestpublicvoidtestDeleteData(){client.path("sample/removeData/23").delete();}@TestpublicvoidtestPostData(){Useruser=newUser();user.setId(21432134);user.setAddress("hoojo#gz");user.setEmail("hoojo_@126.com");user.setName("hoojo");System.out.println(client.path("sample/postData").accept(MediaType.APPLICATION_XML).post(user,User.class));}@TestpublicvoidtestPutData(){Useruser=newUser();user.setId(21432134);System.out.println(client.path("sample/putData/1").accept(MediaType.APPLICATION_XML).put(user).getEntity());}}
如果你喜欢用Spring的方式,还需要在applicationContext-client.xml中增加如下配置<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans'target='_blank'>http://www.springframework.org/schema/beans/spring-beans-3.0.xsd[/code] 'target='_blank'>http://www.springframework.org/schema/context[/code] 'target='_blank'>http://www.springframework.org/schema/context/spring-context-3.0.xsd[/code] http://cxf.apache.org/jaxws 'target='_blank'>http://cxf.apache.org/schemas/jaxws.xsd">[/code] <beanid="webClient"class="org.apache.cxf.jaxrs.client.WebClient"factory-method="create"><constructor-argtype="java.lang.String"value="http://localhost:8000/CXFWebService/rest/"/></bean></beans>
这种是利用WebClient对象来调用WebService,还有一种方法也可以调用WebService,代码如下://手动创建//RESTSamplesample=JAXRSClientFactory.create("http://localhost:8000/CXFWebService/rest",RESTSample.class);//从SpringIoc容器中拿webClient对象ApplicationContextctx=newClassPathXmlApplicationContext("applicationContext-client.xml");RESTSamplesample=ctx.getBean("restSampleBean",RESTSample.class);System.out.println(sample);System.out.println(sample.doGet());//System.out.println(sample.doRequest("haha",null,null));System.out.println(sample.getBean(22));System.out.println(sample.getList());System.out.println(sample.getMap().getMap());Useruser=newUser();user.setId(21432134);user.setAddress("hoojo#gz");user.setEmail("hoojo_@126.com");user.setName("hoojo");System.out.println(sample.postData(user));System.out.println(sample.putData(111,user));sample.deleteData(2);
这种方式相对比WebClient要简单,直接使用接口中的方法即可。同样如果你要整合到Spring可以在applicationContext-client.xml中增加配置如下:<beanid="restSampleBean"class="org.apache.cxf.jaxrs.client.JAXRSClientFactory"factory-method="create"><constructor-argtype="java.lang.String"value="http://localhost:8000/CXFWebService/rest/"/><constructor-argtype="java.lang.Class"value="com.hoo.service.RESTSample"/></bean>
执行以上方法可以看到控制台打印结果如下:clientconsoleorg.apache.cxf.jaxrs.client.ClientProxyImpl@1cf7491thisisgetrestrequest22#JojO#null#nullcom.hoo.entity.Users@16eb6bc{key-0=0#JojO-0#null#null,key-1=1#JojO-1#null#null,key-2=2#JojO-2#null#null,key-3=3#JojO-3#null#null}21432134#jojo##12321321#hoojo_@126.com#hoojo#gz111#hoojo#hoojo_@126.com#hoojo#gzserverconsole####getBean#####id:22Method:GETuri:sample/bean/22{id=[22]}####getList#####Method:GETuri:sample/list{}####getMap#####Method:GETuri:sample/map{}21432134#hoojo#hoojo_@126.com#hoojo#gz#####putData#####21432134#hoojo#hoojo_@126.com#hoojo#gz111#hoojo#hoojo_@126.com#hoojo#gz#######deleteData#######2
就这样,整合restfulWebService成功。
本文出自:http://www.cnblogs.com/hoojo/archive/2012/07/23/2605219.html
相关文章推荐
- Spring REST是什么?
- Spring REST
- Spring REST
- spring rest
- Spring REST
- Spring REST
- Spring REST配置指南与问题总结
- Spring REST是什么?(转)
- Spring REST
- Spring REST
- Spring REST
- Spring REST 配置CSRF防护
- Spring REST
- Spring REST实践之安全
- spring rest 接收json数据
- Spring rest
- Spring rest对etag支持
- Spring rest 4.0
- Spring rest对etag支持
- Spring Rest的注解annotation和配置文档(ContentNegotiatingViewResolver)的区别