CXF学习笔记三(发布restFul)
一、概述
JAX-RS是Java提供用于开发RESTful Web服务基于注解(annotation)的API。JAX-RS旨在定义一个统一的规范,使得Java程序员可以使用一套固定的接口来开发REST应用,避免了依赖第三方框架。同时JAX-RS使用POJO编程模型和基于注解的配置并集成JAXB,可以有效缩短REST应用的开发周期。JAX-RS只定义RESTful API,具体实现由第三方提供,如Jersey、Apache CXF等。
JAX-RS包含近五十多个接口、注解和抽象类:
javax.ws.rs包含用于创建RESTful服务资源的高层次(High-level)接口和注解。
javax.ws.rs.core包含用于创建RESTful服务资源的低层次(Low-level)接口和注解。
javax.ws.rs.ext包含用于扩展JAX-RS API支持类型的APIs。
JAX-RS常用注解:
@Path:标注资源类或方法的相对路径。
@GET、@PUT、@POST、@DELETE:标注方法的HTTP请求类型。
@Produces:标注返回的MIME媒体类型。
@Consumes:标注可接受请求的MIME媒体类型。
@PathParam、@QueryParam、@HeaderParam、@CookieParam、@MatrixParam、@FormParam:标注方法的参数来自于HTTP请求的位置。@PathParam来自于URL的路径,@QueryParam来自于URL的查询参数,@HeaderParam来自于HTTP请求的头信息,@CookieParam来自于HTTP请求的Cookie。
二、依赖JAR文件Maven坐标
<properties> <cxf.version>3.0.7</cxf.version> <junit.version>4.11</junit.version> </properties> <!-- CXF需要导入的jar包 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf.version}</version> </dependency> <!-- CXF实现RestFul接口需要用到的包 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>${cxf.version}</version> </dependency> <!-- 客户端调用restFul服务需要导入的包 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>${cxf.version}</version> </dependency> <!-- 部署至tomcat低下不会,jetty环境需要加入该包 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>${cxf.version}</version> </dependency>
三、发布RestFul接口
3.1实体对象
/** * @author Ickes */ @XmlRootElement(name="UserInfo") public class Users{ private String userId; private String userName; private String userPwd; private Integer sex; private Float sal; private Date birthday; get、set方法省略! public String toJson() { Gson gson = new Gson(); return gson.toJson(this); } }
3.2、定义发布接口
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 javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; /** * 用户服务接口 * @author Ickes */ @Path("/restFul") public interface UserService { /** * 测试GET方法,传人对象、普通参数;返回对象 * */ @GET @Path("/get") @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) public Users get(@QueryParam("id") String id); /** * 测试PUT方法,传人对象、普通参数;返回对象 * id来源于url后面的参数 * @param user * @return */ @PUT @Path("/put/{id}") @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) public Users put(@PathParam("id")String id,Users u); /** * 测试POST方法,传人对象、普通参数;返回对象 * */ @POST @Path("/post/{id}") @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) public Users post(@PathParam("id") String id,Users u); /** * 测试DELETE方法 ,传人普通参数;返回对象 */ @DELETE @Path("/delete/{id}") @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) public Users delete(@PathParam("id") String id); }
3.3、接口实现类
import java.util.Date; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; /** * 用户服务实现类 * * @author Ickes */ public class UserServiceRestFul implements UserService { @Override public Users get(String id) { System.out.println("GET方法,id=" + id); Users user = new Users(); user.setUserId("get"); user.setUserName("ickes"); user.setUserPwd("ices123"); user.setSex(1); user.setSal(32F); user.setBirthday(new Date()); return user; } @Override public Users put(String id, Users u) { System.out.println("PUT方法,id=" + id + ",users=" + u.toJson()); Users user = new Users(); user.setUserId("put"); user.setUserName("ickes"); user.setUserPwd("ices123"); user.setSex(1); user.setSal(32F); user.setBirthday(new Date()); return user; } @Override public Users post(String id, Users u) { System.out.println("POST方法,id=" + id + ",users=" + u.toJson()); Users user = new Users(); user.setUserId("post"); user.setUserName("ickes"); user.setUserPwd("ices123"); user.setSex(1); user.setSal(32F); user.setBirthday(new Date()); return user; } @Override public Users delete(String id) { System.out.println("DELETE方法,id=" + id); Users user = new Users(); user.setUserId("delete"); user.setUserName("ickes"); user.setUserPwd("ices123"); user.setSex(1); user.setSal(32F); user.setBirthday(new Date()); return user; } }
四、发布RestFul接口
4.1、使用CXF的API接口进行发布
使用CXF的API接口进行发布的缺点很明显,就是必须指定一个端口进行发布,这个端口不能被占用,占用就会抛出异常。
/** * 使用CXF发布RestFul服务 * * @param args */ public static void main(String[] args) { JAXRSServerFactoryBean jrf = new JAXRSServerFactoryBean(); jrf.setResourceClasses(UserServiceRestFul.class); jrf.setResourceProvider(UserServiceRestFul.class, new SingletonResourceProvider(new UserServiceRestFul())); jrf.setAddress("http://localhost:8080/rest/"); jrf.create(); }
4.2、在spring容器中进行发布
跟使用CXF发布JAX-WS接口一样,首先必须在web.xml中配置CXFWebServlet,代码如下:
<!-- Cxf中使用 CXFServlet,发布跟当前项目端口相同的服务 --> <servlet> <servlet-name>cxfServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>cxfServlet</servlet-name> <url-pattern>/cxf/*</url-pattern> </servlet-mapping>
然后在类路径下面新建applicationContext-cxf.xml,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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 http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd "> <jaxrs:server id="restUserService" address="/restFul"> <jaxrs:serviceBeans> <ref bean="userServiceRestFul" /> </jaxrs:serviceBeans> <jaxrs:extensionMappings> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </jaxrs:extensionMappings> </jaxrs:server> <bean id="userServiceRestFul" class="com.gosun.jws.cxf.restful.UserServiceRestFul"></bean> </beans>
发布后在浏览器中输入http://localhost:8080/jws/cxf,出现如下见面说明发布成功.
五、客户端调用
5.1、使用WebClient进行调用(不推荐)
使用org.apache.cxf.jaxrs.client.WebClient调用的代码如下:
import javax.ws.rs.core.MediaType; import org.apache.cxf.jaxrs.client.WebClient; import org.junit.Before; import org.junit.Test; /** * @author Ickes */ public class WebClientTest { WebClient client = null; @Before public void init() { client = WebClient.create("http://localhost:8080/rest/"); } /** * 调用get方法,get方式是将参数加入到URL地址后面的,所以不能传人Bean,但是可以转换为json的格式进行传递 * * @param client */ @Test public void getTest() { // 测试URL传递数据 client = WebClient .create("http://localhost:8080/rest/restFul/get?id=ickes"); Users u = client.accept(MediaType.APPLICATION_XML).get(Users.class); System.out.println(u.toJson()); } /** * 调用put方法,可以看到这种方式可以传人一个JavaBean参数, 但是集合对象不行,可以将集合写在JavaBean里面进行传递 */ @Test public void putTest() { Users u = new Users(); u.setUserId("1"); u.setUserName("aa"); u.setUserPwd("bbb"); client.path("restFul/put/{id}", "ickes") .accept(MediaType.APPLICATION_XML).put(u); } /** * 调用post方法,这种方式的调用跟put方式异曲同工 * */ @Test public void postTest() { Users u = new Users(); u.setUserId("1"); u.setUserName("aa"); u.setUserPwd("bbb"); client.accept(MediaType.APPLICATION_XML) .path("/restFul/post/{id}", "post").post(u); } /** * 调用Delete方法,这个方法可以看到delete方法是不能传递参数的,只能通过其他方式,例如URL * */ @Test public void deleteTest() { client.accept(MediaType.APPLICATION_XML) .path("/restFul/delete/{id}", "post").delete(); } }
5.2、使用CXF的客户端工厂类JAXRSClientFactory进行调用(推荐)
这种方式相对比WebClient要更简单,直接使用接口中的方法即可,代码如下:
import org.apache.cxf.jaxrs.client.JAXRSClientFactory; import org.junit.Before; import org.junit.Test; /** * <pre> * 调用RestFul接口,除了使用WebClient意外,还可以使用org.apache.cxf.jaxrs.client.JAXRSClientFactory; * 这种方式相对比WebClient要更简单,直接使用接口中的方法即可 * </pre> * * @author Ickes */ public class JAXRSClientFactoryTest { UserService us = null; @Before public void init() { us = JAXRSClientFactory.create("http://localhost:8080/jws/cxf/restFul",UserService.class); System.out.println(us); } /** * 调用get方法 */ @Test public void getTest() { System.out.println(us.get("a").toJson()); } /** * 调用put方法 */ @Test public void putTest() { Users u = new Users(); u.setUserId("1"); u.setUserName("aa"); u.setUserPwd("bbb"); System.out.println(us.post("a001",u)); } /** * 调用post方法 * */ @Test public void postTest() { Users u = new Users(); u.setUserId("1"); u.setUserName("aa"); u.setUserPwd("bbb"); us.post("POST", u); } /** * 调用Delete方法 * */ @Test public void deleteTest() { us.delete("DELETE"); } }
如果想在Spring配置文件中配置org.apache.cxf.jaxrs.client.JAXRSClientFactory,代码如下:
<bean id="userService" class="org.apache.cxf.jaxrs.client.JAXRSClientFactory" factory-method="create"> <constructor-arg type="java.lang.String" value="http://localhost:8080/rest/" /> <constructor-arg type="java.lang.Class" value="com.gosun.jws.cxf.restful.UserService" /> </bean>