您的位置:首页 > 编程语言 > Java开发

spring整合cxf实现restful webservice

2017-08-08 15:56 856 查看
WebService入门

WebService(注解),CXF框架(jax-ws,Jax-rs,与spring整合)

闲下来研究webservice也好几天了,百度上纷繁错杂的文章令人眼花缭乱,看着都头疼,有的文章讲的更不知从何说起;好在终于找到上面两份连贯性的文章,就此让我对webservice有了系统的认识,也知道如何去进行代码的实现;

那么既然已经了解的差不多了,那咱们就写个demo练练手吧,顺便也给自己和后来的小伙伴留下点东西,熟悉的更快点。

一、导入支撑包到web工程的lib下

我这没有新建maven项目,所以都是手动导包;如果你是新建的maven项目,那么添加依赖就好了,至于导入那些依赖包,我就不贴出来了,各位下载附件代码吧;



二、创建实体Bean

package cn.Higgin.ws.mobile.bean;

import javax.xml.bind.annotation.XmlRootElement;

/**
*
* @author Administrator
* 如果返回值为Order、List<Order>类型,且数据格式是xml,
* 则必须添加下面的注解。
*/
@XmlRootElement(name="order")
public class Order {
private Integer id;
private String name;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Order [id=" + id + ", name=" + name + "]";
}
}


三、服务类接口

javax.ws.rs.GET;
javax.ws.rs.POST;
javax.ws.rs.Path;
javax.ws.rs.PathParam;
javax.ws.rs.Produces;
javax.ws.rs.QueryParam;
javax.ws.rs.core.MediaType;.....

在接口类和方法上分别利用javax.ws.rs.*包下的注解定义类路径(@Path)、方法路径(@Path)、方法请求类型(@GET,@POST..)、方法返回值响应类型(@Produces)

package cn.Higgin.ws.mobile.service;

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
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 cn.Higgin.ws.mobile.bean.Order;

/**
*
* @author Administrator
* @Produces:响应支持多个 MIME 类型。在本例和上一个示例中,APPLICATION/XML 将是默认的 MIME 类型。</br>
*
* <p>cxf restful 返回值支持数据类型:</p></br>
* <p>(一)、基本类型:(@Produces需设置为:MediaType.TEXT_PLAIN,MediaType.APPLICATION_JSON)</p></br>
*         </p>–int,float,boolean等</p></br>
* <p>(二)、应用类型:String、自定义类型:Order、集合类型:数组,List, Set, Map</p></br>
*
*/
@Path("/mo")
public interface MobileService {

/**
* 返回基本类型数据:int
*
* @param id
* @return
*/
@POST
@Path("/queryOrder3/{id}")
@Produces({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON })
public int queryOrder3(@PathParam("id") Integer id);

@GET
@Path("/queryMobile/{phone}")
@Produces({ MediaType.APPLICATION_JSON })
public String queryMobile(@PathParam("phone") String phone);

@GET
@Path("/queryOrder/{id}")
@Produces({ MediaType.APPLICATION_JSON })
// http://localhost:8080/webservice_spring_mobile_server_resful/ws/mobile2/mo/queryOrder/13167173501 public Order queryOrder(@PathParam("id") String id);

@GET
@Path("/queryOrderList")
@Produces({ MediaType.APPLICATION_JSON })
public List<Order> queryOrderList();

@GET
@Path("/queryMobile1")
@Produces({ MediaType.APPLICATION_JSON })
// http://localhost:8080/webservice_spring_mobile_server_resful/ws/mobile2/mo/queryMobile1?phone=13167173501 public String queryMobile1(@QueryParam("phone") String phone);

@POST
@Path("/queryOrder1/{id}")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Order queryOrder1(@PathParam("id") int id);

@POST
@Path("/queryOrder2/{id}")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Order queryOrder2(@PathParam("id") Integer id);

/**
* 集合类型:数组 基本类型
*
* @param id
* @return
*/
@POST
@Path("/getArray/{id}")
@Produces({ MediaType.APPLICATION_JSON })
public int[] getArray(@PathParam("id") Integer id);

/**
* 集合类型:数组 对象类型
*
* @param id
* @return
*/
@POST
@Path("/getArrayObj/{id}")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Order[] getArrayObject(@PathParam("id") Integer id);

/**
* 集合类型:List
*
* @param order
* @return
*/
@POST
@Path("/queryOrders")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public List<Order> queryOrders(Order order);

@POST
@Path("/getSetObj")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Set<Order> getSetObjSet(Order order);

@POST
@Path("/getSetBasic")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Set<Integer> getSetBasicSet(Order order);

@POST
@Path("/getMapBasic")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Map<Integer,Order> getSetBasicMap(Order order);

}
前面两个文章只是在示例中使用了以上的类、或者方法注解,但是并没告诉大家这些注解是干嘛的,到底该怎么去使用;下面,我们就来理一下。

1、概述


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。
这些注释均可在资源、资源方法、子资源方法、子资源定位器或子资源内找到。

@Produces:返回的类型

注释代表的是一个资源可以返回的 MIME 类型

a.返回给client字符串类型(text/plain)

[java] view
plain copy

@Produces(MediaType.TEXT_PLAIN)

b.返回给client为json类型(application/json)

[java] view
plain copy

@Produces(MediaType.APPLICATION_JSON)

测试:

string类型:

[java] view
plain copy

@Path("/say")

@GET

@Produces(MediaType.TEXT_PLAIN)

public String say() {

System.out.println("hello world");

return "hello world";

}

json和bean类型:

[java] view
plain copy

@Path("test")

@GET

@Produces(MediaType.APPLICATION_JSON)

public Result<String> test() {

Result<String> result = new Result<String>();

result.success("aaaaaa");

return result;

}

@Path("bean")

@GET

@Produces(MediaType.APPLICATION_JSON)

public UserBean bean() {

UserBean userBean = new UserBean();

userBean.setId(1);

userBean.setUsername("fengchao");

return userBean;

}

@
Consumes
注释代表的是一个资源可以接受的
MIME 类型


@Consumes
@Produces
相反,用来指定可以接受client发送过来的MIME类型,同样可以用于class或者method,也可以指定多个MIME类型,一般用于
@PUT
,@POST

a.接受client参数为字符串类型

[java] view
plain copy

@Consumes(MediaType.TEXT_PLAIN) b.接受clent参数为json类型

@Consumes(MediaType.APPLICATION_JSON)

@PathParam

这种注解是负责捕获URL路径中的参数值。例如:

[plain] view
plain copy






http://host:port/your-service/{path-param-1}/{path-param-2}
[java] view
plain copy

@GET

@Path("{username"})

@Produces(MediaType.APPLICATION_JSON)

public User getUser(@PathParam("username") String userName) {

...

}

@QueryParam

这种注解是负责捕获URL路径中的参数值。例如:

[plain] view
plain copy






http://host:port/your-service/{path-param-1}/{path-param-2}
同时,你的服务端方法应该这样使用:

[java] view
plain copy

@GET

@Path("/user")

@Produces("text/plain")

public User getUser(@QueryParam("name") String name,

@QueryParam("age") int age) {

...

}

如果需要为参数设置默认值,可以使用
@DefaultValue
,如:

[java] view
plain copy

@GET

@Path("/user")

@Produces("text/plain")

public User getUser(@QueryParam("name") String name,

@DefaultValue("26") @QueryParam("age") int age) {

...

}

@FormParam

获取post请求中表单中的数据:



[java] view
plain copy

@POST

@Consumes("application/x-www-form-urlencoded")

public void post(@FormParam("name") String name) {

// Store the message

}

@BeanParam
获取请求参数中的数据,用实体Bean进行封装

[java] view
plain copy

@POST

@Consumes("application/x-www-form-urlencoded")

public void update(@BeanParam User user) {

// Store the user data

}

@MatrixParam

这种注解大家可能用的不多,是负责捕获URL路径中的matrix参数的值。例如:

[plain] view
plain copy






http://host:port/your-service/matrix;id=1;name=tom
同时,你的方法是这样的:

[java] view
plain copy







public String getMatrixParam(@MatrixParam("id") String id, @MatrixParam("name") String name);

@HeaderParam

这种注解是负责捕获HTTP请求头中的参数的值。例如:

[plain] view
plain copy






http://host:port/your-service/getHeader


同时,你的方法是这样的:

[java] view
plain copy







public String getHeader(@HeaderParam("user-agent") String userAgent);



四、接口实现类

实现类只需实现接口,无需再添加任何注解。

package cn.Higgin.ws.mobile.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.Higgin.ws.mobile.bean.Order;

import com.cosw.juhe.JuHeUtil;

public class MobileServiceImpl implements MobileService {

@Override
public String queryMobile(String phone) {
return JuHeUtil.getRequest(phone);
}

@Override
public Order queryOrder(String id) {
Order order =new Order();
order.setId(1);
order.setName("name");
return order;
}

@Override
public List<Order> queryOrderList() {
List<Order> orders=new ArrayList<Order>();
Order order1=new Order();
order1.setId(1);
order1.setName("name");
orders.add(order1);

Order order2=new Order();
order2.setId(2);
order2.setName("name2");
orders.add(order2);
return orders;
}

@Override
public String queryMobile1(String phone) {
return phone;
}

@Override
public List<Order> queryOrders(Order order) {
System.out.println("queryOrders:"+order);
List<Order> orders=new ArrayList<Order>();
Order order1=new Order();
order1.setId(1);
order1.setName("name");
orders.add(order1);

Order order2=new Order();
order2.setId(2);
order2.setName("name2");
orders.add(order2);
return orders;
}

@Override
public Order queryOrder1(int id) {
Order order2=new Order();
order2.setId(id);
order2.setName("queryOrder1=>name2");
return order2;
}

@Override
public Order queryOrder2(Integer id) {
Order order2=new Order();
order2.setId(id);
order2.setName("queryOrder2=>name2");
return order2;
}

@Override
public int queryOrder3(Integer id) {
return 25;
}

@Override
public int[] getArray(Integer id) {
int[] arrays=new int[5];
arrays[0]=1;
arrays[1]=2;
arrays[2]=3;
arrays[3]=4;
arrays[4]=5;
return arrays;
}

@Override
public Order[] getArrayObject(Integer id) {
Order[] os=new Order[2];
Order order2=new Order();
order2.setId(id);
order2.setName("queryOrder2=>name2");
os[0]=order2;

Order order3=new Order();
order3.setId(id);
order3.setName("queryOrder2=>name2");
os[1]=order3;
return os;
}

@Override
public Set<Order> getSetObjSet(Order order) {
Set<Order> orders=new HashSet<Order>();
orders.add(order);
return orders;
}

@Override
public Set<Integer> getSetBasicSet(Order order) {
Set<Integer> is=new HashSet<Integer>();
is.add(1);
is.add(2);
is.add(3);
is.add(4);
is.add(5);
return is;
}

@Override
public Map<Integer, Order> getSetBasicMap(Order order) {
Map<Integer, Order> maps=new HashMap<Integer, Order>();
maps.put(1, order);
return maps;
}
}



五、加入spring集成cxf的配置文件,配置cxf发布的路径

具体注意事项不在此处罗嗦了,具体看配置文件吧。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:jaxws="http://cxf.apache.org/jaxws"
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">

<!-- 基础配置 -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<!-- 请求日志拦截器,将会打印请求日志 -->
<bean id="inLogInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<!-- 响应日志拦截器,将会打印响应日志 -->
<bean id="outLogInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />

<!-- 配置本系统的手机号码查询service -->
<bean id="mobileService" class="cn.Higgin.ws.mobile.service.MobileServiceImpl">
</bean>

<!-- 发布手机号查询服务 -->
<!-- soap webservic:此种方式不支持GET请求或者是resful请求,
只能通过webservice客户端调用
-->
<!-- <jaxws:server id="mobileService1" serviceClass="cn.Higgin.ws.mobile.service.MobileService"
address="/mobile1">
<jaxws:serviceBean>
要暴露的 bean 的引用
<ref bean="mobileService" />
</jaxws:serviceBean>
<jaxws:inInterceptors>
<ref bean="inLogInterceptor" />
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<ref bean="outLogInterceptor" />
</jaxws:outInterceptors>
</jaxws:server> -->

<!-- restful webservice:发布restful必须使用jaxrs:server实现 -->
<jaxrs:server id="restServiceContainer" address="/mobile2">
<!-- Interceptors -->
<jaxrs:inInterceptors>
<ref bean="inLogInterceptor" />
</jaxrs:inInterceptors>
<jaxrs:outInterceptors>
<ref bean="outLogInterceptor" />
</jaxrs:outInterceptors>
<!-- serviceBeans -->
<jaxrs:serviceBeans>
<ref bean="mobileService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="feed" value="application/atom+xml" />
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="html" value="text/html" />
</jaxrs:extensionMappings>
<jaxrs:languageMappings>
<entry key="en" value="en-gb" />
<entry key="cn" value="cn-ZH"/>
</jaxrs:languageMappings>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
</jaxrs:providers>
</jaxrs:server>
</beans>


六、web.xml中配置cxf servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebService_Spring_Mobile_Server</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置cxf servlet -->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>


到此处,一个完整的cxf整合spring的restful webservice接结束了。

七、接口调用

虽然到这边结束了,但是我们还是得写个客户端验证下我们自己写的接口是不是按我们预想的输出数据,此处我就不一一把接口运行效果贴出来了,需要验证的小伙伴可以按例子自己做一下或者下载demo跑一下,自己验证下。

package com.cosw.test.test;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import com.cosw.test.bean.Order;
import com.cosw.test.util.HttpClientUtil;

public class ResfulTest {
public static final String prefix = "http://localhost:8080/webservice_spring_mobile_server_resful/ws/mobile2/mo/";
public static final String QUERY_ORDERS = prefix + "queryOrders?_type=xml";
public static final String QUERY_ORDER1 = prefix + "queryOrder1/1";
public static final String QUERY_ORDER2 = prefix + "queryOrder2/2";
public static final String QUERY_ORDER3 = prefix + "queryOrder3/3";
public static final String GET_ARRAY = prefix + "getArray/3";
public static final String GET_ARRAY_OBJ = prefix + "getArrayObj/3";
public static final String GET_ARRAY_OBJ_JSON = prefix
+ "getArrayObj/3?_type=json";
public static final String GET_ARRAY_OBJ_XML = prefix
+ "getArrayObj/3?_type=xml";
public static final String GET_SET_OBJ = prefix + "getSetObj";
public static final String GET_SET_BASIC = prefix + "getSetBasic";
public static final String GET_MAP_BASIC = prefix + "getMapBasic";

public static void main(String[] args) {
// queryOrders();

/* queryOrder1(); */
/* queryOrder2(); */
/* queryOrder3(); */

/* getArray(); */
/*getArrayObj();*/
getSetBasic();
getSetObj();
getMap();
}

public static void queryOrders() {
Order order = new Order();
order.setId(1);
order.setName("我进来看看...");
try {
System.out.println(HttpClientUtil.postRequest(QUERY_ORDERS,
objToJsonStr(order)));
} catch (Exception e) {
e.printStackTrace();
}
}

public static void queryOrder1() {
try {
System.out.println(HttpClientUtil.postRequest(QUERY_ORDER1,
new HashMap<String, Object>()));
} catch (Exception e) {
e.printStackTrace();
}
}

public static void queryOrder2() {
try {
System.out.println(HttpClientUtil.postRequest(QUERY_ORDER2,
new HashMap<String, Object>()));
} catch (Exception e) {
e.printStackTrace();
}
}

public static void queryOrder3() {
try {
System.out.println(HttpClientUtil.postRequest(QUERY_ORDER3,
new HashMap<String, Object>()));
} catch (Exception e) {
e.printStackTrace();
}
}

// 获取基本数据类型数组:int[]
public static void getArray() {
try {
System.out.println(HttpClientUtil.postRequest(GET_ARRAY,
new HashMap<String, Object>()));
} catch (Exception e) {
e.printStackTrace();
}
}

// 获取对象类型数组:order[]
public static void getArrayObj() {
try {
System.out.println(HttpClientUtil.postRequest(GET_ARRAY_OBJ,
new HashMap<String, Object>()));
} catch (Exception e) {
e.printStackTrace();
}
}

public static void getSetBasic() {
Order order = new Order();
order.setId(1);
order.setName("我进来看看...");
try {
System.out.println("getSetBasic:"+HttpClientUtil.postRequest(GET_SET_BASIC,
objToJsonStr(order)));
} catch (Exception e) {
e.printStackTrace();
}
}

public static void getSetObj() {
Order order = new Order();
order.setId(1);
order.setName("我进来看看...");
try {
System.out.println("getSetObj:"+HttpClientUtil.postRequest(GET_SET_OBJ,
objToJsonStr(order)));
} catch (Exception e) {
e.printStackTrace();
}
}

public static void getMap() {
Order order = new Order();
order.setId(1);
order.setName("我进来看看...");
try {
System.out.println("getMap:"+ HttpClientUtil.postRequest(GET_MAP_BASIC,
objToJsonStr(order)));
} catch (Exception e) {
e.printStackTrace();
}
}

public static String objToJsonStr(Object obj) {
ObjectMapper mapper = new ObjectMapper();
String mapJakcson = null;
try {
mapJakcson = mapper.writeValueAsString(obj);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return mapJakcson;
}
}


GitHub下载地址:https://github.com/TaavettiTao/webservice.git



本站地址:http://download.csdn.net/download/u012454773/9925098
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息