使用Apache cxf 开发restful webservice 服务的实例

由于最近自己要写几个与外围系统的数据交互接口,并且要使用的webservice;公司最近改革用比较新颖的基于RESTFUL方式的webservice。

之前转过几篇关于RESTFUL框架的介绍,这里就再次做阐述了;废话不多说,下面直接开始上代码:

由于是基于maven 、spring 和cxf上进行搭建的服务;所以首先要大家maven工程;

(1)在pom中引入cxf 、spring的依赖

<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring-version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
			<version>${cxf-version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-tools-common</artifactId>
			<version>${cxf-version}</version>
		</dependency>
		<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-testutils</artifactId>
			<version>${cxf-version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>${cxf-version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http-jetty</artifactId>
			<version>${cxf-version}</version>
			<scope>test</scope>
		</dependency>
又因为是在jetty下部署,所以pom要引入jetty的插件的依赖

<plugins>
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>jetty-maven-plugin</artifactId>
				<version>7.5.0.v20110901</version>
				<configuration>
					<webAppConfig>
						<contextPath>/test</contextPath>
					</webAppConfig>
				</configuration>
			</plugin>
(2创建pojo   我这里创建了一个请求和响应的类
/** 
 * @ClassName: Request 
 * @Description: 请求消息 
 * @author leo 
 * @date 2014-8-4 上午10:17:31  
 */ 
  
public class Request {
	
	/**
	 * @Fields n_id : 工号
	 */
	private String n_id;
	
	/**
	 * @Fields n_name : 姓名
	 */
	private String n_name;
	
	/**
	 * @Fields n_passwd : 密码
	 */
	private String n_passwd;

	/**
	 * @return the n_id
	 */
	public String getN_id() {
		return n_id;
	}

	/**
	 * @param n_id the n_id to set
	 */
	public void setN_id(String n_id) {
		this.n_id = n_id;
	}

	/**
	 * @return the n_name
	 */
	public String getN_name() {
		return n_name;
	}

	/**
	 * @param n_name the n_name to set
	 */
	public void setN_name(String n_name) {
		this.n_name = n_name;
	}

	/**
	 * @return the n_passwd
	 */
	public String getN_passwd() {
		return n_passwd;
	}

	/**
	 * @param n_passwd the n_passwd to set
	 */
	public void setN_passwd(String n_passwd) {
		this.n_passwd = n_passwd;
	}
	
}
response 类

/** 
 * @ClassName: Response 
 * @Description: 响应结果 
 * @author leo 
 * @date 2014-8-4 上午10:19:32  
 */ 
@XmlRootElement(name="Response")  
public class Response {
	
	/**
	 * @Fields is_state : 登陆状态
	 */
	private boolean is_state;
	
	/**
	 * @Fields cause : 登陆结果
	 */
	private String cause;
	
	/**
	 * @return the is_state
	 */
	public boolean isIs_state() {
		return is_state;
	}

	/**
	 * @param is_state the is_state to set
	 */
	public void setIs_state(boolean is_state) {
		this.is_state = is_state;
	}

	/**
	 * @return the cause
	 */
	public String getCause() {
		return cause;
	}

	/**
	 * @param cause the cause to set
	 */
	public void setCause(String cause) {
		this.cause = cause;
	}

	/* (非 Javadoc) 
	 *  
	 *  
	 * @return 
	 * @see java.lang.Object#toString() 
	 */ 
	@Override
	public String toString() {
		return "Response [is_state=" + is_state + ", cause=" + cause + "]";
	}
	
}

【注】: 注解@XmlRootElement指定response为XML的根元素。response类的属性默认指定映射为@XmlElement。@XmlElement用来定义XML中的子元素。@XmlRootElement和@XmlElement允许自定义命名空间和XML中元素的名称。如果没有定义的话,JAXB在运行的时候默认的使用同样的属性名和类名来定义XML元素。

(3)创建服务端

我这里是创建了一个模拟登录的接口服务,  创建ILogin.java 的接口, 已经实现接口服务的实现类,实现了RESTFUL的get post请求

/**
 * @ClassName: Loginimpl
 * @Description: 登陆接口实现
 * @author leo
 * @date 2014-8-4 上午10:22:09
 */
@Path("/loginService")
@Produces({MediaType.APPLICATION_JSON}) //返回的类型是JSON
@Consumes({MediaType.APPLICATION_JSON}) //资源方法能够处理的类型是JSON ,
public class Loginimpl implements ILogin {

	private static final Log LOG = LogFactory.getLog(Loginimpl.class);

	@Override
	@POST
	@Path("/index")  //指定路径是:basePath+/index
	public Response login(Request request) {
		try {
			LOG.info("正在调用POST请求");
			LOG.info(request.getN_name());
			Response rs = new Response();
			rs.setIs_state(true);
			rs.setCause("login success");
			return rs;
		} catch (Throwable throwable) {
			return null; 
		}
	}

	@Override
	@GET
	@Path("/login")  //指定路径是basePath+/login
	public Response login(@Context HttpServletResponse response) {
		LOG.info("正在调用GET请求");
		Response rs = new Response();
		rs.setIs_state(true);
		rs.setCause("login success");
		response.addHeader("ESB-ResultCode", "1");
		return rs;
	}

}
【注】:service类 使用@Path、@Produces 、@Consumes、@get @POST 等注解,指明了登录服务的给路径 是basePath+/login ,@Produces 是用来表示资源类方法能够返回的类型是JOSN,@Consumes 表示资源类方法能否处理的方法是JOSN类型的

接下来要在spring.xml 中配置上server 和login注入依赖:

	<jaxrs:server id="mamApplication" address="/rest">
<span style="white-space:pre">		</span><jaxrs:serviceBeans>
<span style="white-space:pre">			</span><!-- 用户登陆 -->
<span style="white-space:pre">			</span><ref bean="login" />
<span style="white-space:pre">			</span>
<span style="white-space:pre">		</span></jaxrs:serviceBeans>
<span style="white-space:pre">		</span><jaxrs:extensionMappings>
<span style="white-space:pre">			</span><entry key="json" value="application/json" />
<span style="white-space:pre">		</span></jaxrs:extensionMappings>
<span style="white-space:pre">		</span><jaxrs:languageMappings>
<span style="white-space:pre">			</span><entry key="en" value="en-gb" />
<span style="white-space:pre">		</span></jaxrs:languageMappings>
<span style="white-space:pre">		</span><jaxrs:providers>
<span style="white-space:pre">			</span><ref bean="jacksonJsonProvider" />
<span style="white-space:pre">		</span></jaxrs:providers>
<span style="white-space:pre">	</span></jaxrs:server>
<span style="white-space:pre">	</span><bean id="login" class="com.deppon.rest.service.impl.Loginimpl" />
<span style="white-space:pre">	</span><!-- 定义jackson 日期转换格式 -->
<span style="white-space:pre">	</span><bean id="simpleDataformat" class="java.text.SimpleDateFormat">
<span style="white-space:pre">		</span><constructor-arg value="yyyy-MM-dd HH:mm:ss"></constructor-arg>
<span style="white-space:pre">	</span></bean>
<span style="white-space:pre">	</span><!-- jackson mapper -->
<span style="white-space:pre">	</span><bean id="mapper" class="org.codehaus.jackson.map.ObjectMapper">
<span style="white-space:pre">		</span><property name="dateFormat" ref="simpleDataformat"></property>
<span style="white-space:pre">	</span></bean>
<span style="white-space:pre">	</span><!-- jackson provider -->
<span style="white-space:pre">	</span><bean id="jacksonJsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider">
<span style="white-space:pre">		</span><property name="mapper" ref="mapper" />
<span style="white-space:pre">	</span></bean>

【注】:关于序列化问题, cxf中的数据序列化是可以替换掉使用你实现MessageBodyReader<Object>和MessageBodyWriter<Object>接口就可以啦,针对xml,cxf采用stax2、jaxb、xmlschema、Woodstox库,针对json默认使用jettison实现的几乎都是codehaus作品。知道cxf序列化和反序列化方式就比较容易解决问题啦。默认情况下cxf的jettison对泛型序列化存在问题,因为道行浅,没有具体去研究实现问题,我之前使用过jackson,去处理json问题,而且cxf拥有jackson的MessageBodyReader和MessageBodyWriter实现类,我只要导入包并告诉cxf使用我指定的json provider就可以了,所以在客户端和服务器端双方都指定json privoder,jackson 库对json序列化实现非常的到位,异常的强大 。

(4)接下来就是客户端 ,使用org.apache.cxf.jaxrs.client.WebClient调用RESTful服务;

<pre name="code" class="java">/** 
 * @ClassName: ApalicationCxfHttp 
 * @Description: 利用cxf创建http客户端
 * @author leo 
 * @date 2014-8-7 上午8:38:24  
 */ 
public class ApalicationCxfHttp {
	
	private static final Log LOG = LogFactory.getLog(ApalicationCxfHttp.class);
	
	private static ApalicationCxfHttp apalicationCxfHttp = new ApalicationCxfHttp();
	
	/**
	 * @Fields client : httpClient
	 */
	//使用org.apache.cxf.jaxrs.client.WebClient调用RESTful服务
	private static WebClient client;
	/**
	 *  创建http客户端
	 */
	public static final ApalicationCxfHttp createClient(String uri){
		client = WebClient.create(uri);
		client.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
		return apalicationCxfHttp;
	}
	
	public static final Object invoke(Object obj,Class<?> cls){
		try {
			//json的转换
			String json = JacksonTransformer.java2String(obj);
			Response response = client.post(json);
			//
			String message = IOUtils.toString((InputStream) response.getEntity());
			return JacksonTransformer.string2java(message, cls);
		} catch (JsonGenerationException e) {
			LOG.error(e.getMessage(), e);
		} catch (JsonMappingException e) {
			LOG.error(e.getMessage(), e);
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
		}
		return null;
	}
	
}



【注】:期间要用到jackson 对json序列化,这里写了一个JacksonTransformer的转换的工具类;
(5)由于是居于webApp下的 要在web.xml 中配置cxfServlet 和spring的监听
<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:com/deppon/rest/META-INF/ds-spring.xml</param-value>
	</context-param>
	 <filter>
        <filter-name>encodingFilter</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>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
	<!-- 日志配置文件的位置 -->
	<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>/WEB-INF/log4j.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<servlet>
        <servlet-name>CXFService</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    </servlet>
  
    <servlet-mapping>
        <servlet-name>CXFService</servlet-name>
        <url-pattern>/rs/*</url-pattern>
    </servlet-mapping>
(6) 启动 jetty 服务器,写了一个junit的测试类 ,测试post请求服务

public class ClientTest {
	private final String uri = "http://localhost:8080/test/rs/rest/loginService/index";
	private static final Log LOG = LogFactory.getLog(ClientTest.class);
	@Test
	public void cxfTest(){
		ApalicationCxfHttp.createClient(uri);
		Response response = (Response) ApalicationCxfHttp.invoke(createRequest(), Response.class);
		LOG.info(response.toString());
	}
	public Request createRequest(){
		Request request = new Request();
		request.setN_id("000001");
		request.setN_name("老板");
		request.setN_passwd("123456");
		return request;
	}
}
结果是可以登录成功,说明webService服务成功了



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值