Spring4 + CXF3.1.5 RESTful Web Service 实战例子 (调试通过)

RESTful 简化了 web service 的设计,它不再需要 wsdl ,也不再需要 soap 协议,而是通过最简单的 http 协议传输数据 ( 包括 xml  json) 。既简化了设计,也减少了网络传输量(因为只传输代表数据的 xml  json ,没有额外的 xml 包装),JAX-RS ,全称 Java API for RESTful WebService。该规范定义了一系列的注解。

下面为大家介绍使用 cxf 开发 RESTful WebService

Cxf3.1.5 实现 jax-rs 的全套规范。在使用它时,最好全部包含它的lib(在它安装目录下的lib下面),从其官网上下载apache-cxf-3.1.5.zip,解压后,在解压的lib目录就是运行时需要的文件。

服务端

Spring4 +cxf3.1.5 开发 RESTfulweb service。

在eclipse上,选择开发动态web 应用项目,然后选择tomcat8作为web server。

然后,在项目视图中选择build path,去添加spring4,cxf3.1.5的lib (为了省事,直接把cxf下面的lib全部包含过来就可以了),如图:

同时,你得把这些libs都copy到 webcontent|web-inf|lib下面去,这样,eclipse在制作WAR文件时,会把这些.jar文件copy到war文件中去。

否则,tomcat会因为找不到这些jar文件而无法启动this web service.

本例子中,开发环境: 

服务器端: eclipse + tomcat8 + CXF3.1.5 + Sring4 

自己得去下载Spring4的jar包和CXF3.1.5的jar包,放到eclipse这个项目的web-content | web-info| lib下面


Client端: eclipse  + CXF3.1.5 + httpclient + JSON + Java SE8


在tomcat上面的运行的server代码

EmployeeWSRestFulService.java (interface)

package cxf.server;

import java.util.*;
import javax.ws.rs.core.*; 
import javax.ws.rs.*;
/**
 * 
 * @author bigtree
 * restful URI 匹配原理,它是咋构成的? access the below page
 *http://blog.csdn.net/bigtree_3721/article/details/51158758
 *
 */
@Path("/")
public interface EmployeeWSRestFulService {
	/**
	 * JSON提交
	 * url:
	 * http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws/addUser
	 * Json format:{"user":{"id":123,"name":"newBook"}}
	 * @param book
	 * @return
	 */
	@Path("/addUser/")
	@POST
	@Consumes({"application/json","application/xml"})
	Response addUser(User user);
	  
	@Path("/delUser/{id}/")
	@DELETE
	@Consumes({"application/json","application/xml"}) 
	Response delUser(@PathParam("id") String id);
	  
	@Path("/updateUser/")
	@PUT
	@Consumes({"application/json","application/xml"})   
	Response updateUser(User user);
	 
	  /* http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws/getUserById/1/
	   * JSON: response content as below
	   * 
	   * HTTP/1.1 200 OK
	   * {"user":{"id":1,"name":"bigtree"}}
	   */
	/*
	 * XML response content as below
		 * HTTP/1.1 200 OK
      1bigtree
		 */
	
	@Path("/getUserById/{id}/")
	@GET
	@Produces({"application/json","application/xml"}) //json is high priority
	User getUserById(@PathParam("id") String id);

	  /* http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws/
	   * response:
	   * HTTP/1.1 200 OK
	   * {"user":[{"id":1,"name":"bigtree"},{"id":2,"name":"jackie"}]}
	   * 
	   */
	@Path("/")
	@GET
	//json is high priority, default is application/xml
	@Produces({"application/json","application/xml"}) 
	List findAllUsers();
	
}

MyServiceImpl.java (server 的实现类)

package cxf.server;
import java.util.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import java.net.URI;  
import javax.ws.rs.core.Response.*; 
public class MyServiceImpl implements EmployeeWSRestFulService {
private void init(){
   User user = new User();
   user.setId("1");
   user.setName("bigtree");
   users.put(user.getId(), user);
   user = new User();
   user.setId("2");
   user.setName("jackie");
   users.put(user.getId(), user);
  }
 
 private HashMap users = new HashMap();
 public MyServiceImpl(){
   init();
 }
 public Response addUser(User user) {
   users.put(user.getId(), user);
   System.out.println("User entity to add: user id= "+user.getId()+" name="+user.getName());
   System.out.println("adding user succeed");
   System.out.println("total users in pool="+users.size());
   return Response.ok().build();
 }
 public Response delUser(String id) {
   User muser=users.remove(id);
   if(muser == null) { 
    // this user with this id not exist
    System.out.println("delUser(): no user entry found to delete");
    return Response.status(Status.BAD_REQUEST).build();
    }
   else
      return Response.ok().build();
 }
 public Response updateUser(User user) {
   users.put(user.getId(), user);
   System.out.println(users.get("1").getName());
   return Response.ok().build();
 }
 public User getUserById(String id) {
 User muser=users.get(id);
 if(muser==null)
 System.out.println("getUserById(): no user entry found");
 return muser;
 }
  public List findAllUsers() {
   List userlist = new ArrayList();
   Iterator userit =  users.keySet().iterator();
   while(userit.hasNext()){
    userlist.add(users.get(userit.next()));
   }
   return userlist;
    }
 }

 Spring 配置文件 applicationContext.xml  配置内容如下, (applicationContext是 Spring从tomcat启动需要的缺省配置文件)



    xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    xsi:schemaLocation=
      "http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
       http://www.springframework.org/schema/cache 
       http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
       http://cxf.apache.org/jaxrs 
       http://cxf.apache.org/schemas/jaxrs.xsd
       ">
            
      
      
        
          
        
       

web.xml 文件配置


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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">
  
  
    
  <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>
  
  <servlet>
        <servlet-name>CXF315servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServletservlet-class>
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>CXF315servlet-name>
        <url-pattern>/WSRest/*url-pattern>
    servlet-mapping>

web-app>

上面绿色部分需要自己写的。

然后在eclipse中以输出上面的项目(eclipse会产生一个.war文件),启动tomcat,然后从进入tomcat管理页面(

缺省是http://localhost:8080),点击"manager app",然后选择“WAR file to deploy”,选择上面产生的war文件,即可部署该web service服务了。


客户端

因为 RESTful 就是利用最原始的 http 协议传输数据,所以客户端其实就是一个 http客户端,有以下几种实现方式

1) JAX-RS Client API --cxf3.0+

2)Proxy 【使用起来简单,代理封装通信细节】

3)Apache HttpClient

4) WebClient

为了简单我使用了 HttpClient方式

代码如下

WSRestFulClient.java

package JAXRSClient;
/*
 * How Request URI is Matched?
 * 
 * http://blog.csdn.net/bigtree_3721/article/details/51158758
 * 
Lets assume 
1) you have a web application called 'rest' (example, a 'rest.war' archive). 
2) CXFServlet's url-pattern is "/test/*" (here it is defined in web.xml as below example shows

CXF315
org.apache.cxf.transport.servlet.CXFServlet
1


CXF315
/WSRest/*

3)  Finally, jaxrs:server's address is "/bar" 
(it is defined in Spring's bean xml such as applicationContext.xml as below shown) 


   


  




Requests like /rest/test/bar or /rest/test/bar/baz will be delivered to one of the resource classes in a given jaxrs:server 
endpoint. For the former request to be handled, a resource class with @Path("/") should be available, in the latter case - 
at least @Path("/") or a more specific @Path("/baz").
 * 
 */


/*
 * Output format:
 * 
 *  http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws/getUserById/1/
 *  
 *  Single user information format:
**   JSON response format as below:
*   HTTP/1.1 200 OK
*   {"user":{"id":1,"name":"bigtree"}}  	   
**  XML response format as below: 
    * HTTP/1.1 200 OK
    * 1bigtree
    * 
* Multi-users response data format:
* JSON response format as below
*  HTTP/1.1 200 OK
*  {"user":[{"id":1,"name":"bigtree"},{"id":2,"name":"jackie"}]}
*
** XML response format as below
 * HTTP/1.1 200 OK
 * 1bigtree2jackie
 */


/* console output 
 * 
 * httpMethodgo(): request string={"user":{"name":"Jane","id":"5"}}
HTTP/1.1 200 OK


HttpPutgo(): request string={"user":{"name":"Jane5","id":"5"}}
HTTP/1.1 200 OK


get one user via Get method of WS-Restful
HTTP/1.1 200 OK
{"user":{"id":5,"name":"Jane5"}}
receive OK rsp
id=5 name=Jane5
get all users via Get method of WS-Restful
HTTP/1.1 200 OK
{"user":[{"id":1,"name":"bigtree"},{"id":2,"name":"jackie"},{"id":5,"name":"Jane5"}]}
receive OK rsp
id=1 name=bigtree
id=2 name=jackie
id=5 name=Jane5
deleting user failed
HTTP/1.1 400 Bad Request


HTTP/1.1 200 OK
{"user":[{"id":1,"name":"bigtree"},{"id":2,"name":"jackie"},{"id":5,"name":"Jane5"}]}
receive OK rsp
id=1 name=bigtree
id=2 name=jackie
id=5 name=Jane5
 * 
 */


import org.apache.http.*;  
import org.apache.http.client.*;   
import org.apache.http.client.methods.*;
import org.apache.http.impl.client.*;
import org.apache.http.util.*;
import org.apache.http.entity.*;


import java.net.URI;
import java.util.*;
import java.io.*;


import org.json.*;
import cxf.server.*;


public class WSRestFulClient {
	public static void main(String[] args) throws Exception {
		 User muser = new User();
		 muser.setId("5");
		 muser.setName("Jane");
		 
		//post method to add user
		 httpMethodgo("http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws/addUser", muser); 
		
		 //put method to update user
		 muser.setName("Jane5");
		 HttpPutgo("http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws/updateUser", muser); 		 
	    /*
		 * get a specified user via ID
		 */
		System.out.println("get one user via Get method of WS-Restful");
		HttpGetgo("http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws/getUserById",5, true);
		
		System.out.println("get all users via Get method of WS-Restful");
		/*
		 * get all users
		 */
		HttpGetgo("http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws",1,false);  
		//delete this user
		 muser.setId("100");
		 HttpDeletego("http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws/delUser", muser); 
		 //get all users again
		 HttpGetgo("http://localhost:8080/MyWebserviceRestfulSpringServer/WSRest/userws",1,false);  
		 return;
	  }
	
	private static void HttpPutgo(String uri, User muser ) throws Exception { 
		 CloseableHttpClient httpclient = HttpClients.createDefault();
		 HttpPut httpMethod = new HttpPut(uri);
		 httpMethod.addHeader("content-type","application/json");


		 JSONObject c = new JSONObject();
		 c.put("name", muser.getName());
		 c.put("id", muser.getId());
		 
		 JSONStringer js = new JSONStringer();
		 js.object();
		 js.key("user").value(c);
		 js.endObject();
		 
		 String ms=js.toString();
		 /** Console output
		  * HttpPutgo(): request string={"user":{"name":"Jane5","id":"5"}}
		  */
		 System.out.println("HttpPutgo(): request string="+ms); 
		 StringEntity entity = new StringEntity(ms,"UTF-8"); 
		 httpMethod.setEntity(entity);
		 CloseableHttpResponse response2 = httpclient.execute(httpMethod);
		 System.out.println(response2.getStatusLine());
		 String rst=EntityUtils.toString(response2.getEntity());
		 /**
		  * console output:
		  * HTTP/1.1 200 OK
		  */
         System.out.println(rst); 
	 }
	
	 private static void httpMethodgo(String uri, User muser) throws Exception { 
		 CloseableHttpClient httpclient = HttpClients.createDefault();
		 HttpPost httpMethod = new HttpPost(uri);
		 httpMethod.addHeader("content-type","application/json");
		 
		 JSONObject c = new JSONObject();
		 c.put("name", muser.getName());
		 c.put("id", muser.getId());
		 
		 JSONStringer js = new JSONStringer();
		 js.object();
		 js.key("user").value(c);
		 js.endObject();
		 
		 String ms=js.toString();
		 /** console output:
		  * httpMethodgo(): request string={"user":{"name":"Jane","id":"5"}}
		  */
		 System.out.println("httpMethodgo(): request string="+ms); 
		 
		 StringEntity entity = new StringEntity(ms,"UTF-8"); 
		 httpMethod.setEntity(entity);
		 
		 CloseableHttpResponse response2 = httpclient.execute(httpMethod);
		 System.out.println(response2.getStatusLine());
		 String rst=EntityUtils.toString(response2.getEntity());
		 /**
		  * HTTP/1.1 200 OK
		  */
         System.out.println(rst);    
	 }
	 
	 private static void HttpGetgo(String resource, Integer userid, boolean SingleResult) throws Exception {  
		 CloseableHttpClient httpclient = HttpClients.createDefault();
		 HttpGet request=null;
		 try {
			 if (SingleResult) {
				 //get one user via id
				request=new HttpGet(resource+"/"+userid.toString());
						 else 	 
			    request = new HttpGet(resource);
			 
			 HttpResponse response = httpclient.execute(request); 
			 try {
				    System.out.println(response.getStatusLine());
				    String rst=EntityUtils.toString(response.getEntity());
	                System.out.println(rst);
	                
	              if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK) {
	                 System.out.println("receive OK rsp");
	                 HttpEntity entity = response.getEntity();
	                 if(entity == null) {
	                	 System.out.println("entity is null");
	                	return;
	                }
	                
	                JSONObject jsonrsp = null;
	                jsonrsp = new JSONObject(new JSONTokener(rst));
	              
	                if(SingleResult==false) {
	                 JSONArray mobj=jsonrsp.getJSONArray("user");
	                 Iterator it=mobj.iterator();
	                 while(it.hasNext()){
	                	JSONObject obj=(JSONObject)it.next();
	                	  System.out.println("id="+obj.getInt("id")+" name="+obj.getString("name"));
	                    } 
	                 } 
	                else {
	                	JSONObject obj=jsonrsp.getJSONObject("user");
	                	System.out.println("id="+obj.getInt("id")+" name="+obj.getString("name"));
	                   }
	                } 	              
	            else {
	                System.out.println("receive error rsp");
	                }
	      	    } 
			finally {
	                ;
	            }
		    } 
		 finally {
	            httpclient.close();
	       }
	 }  


private static void HttpDeletego(String resource, User muser) throws Exception {  
	 CloseableHttpClient httpclient = HttpClients.createDefault();
	 HttpDelete request=null;
	 try {
		 //delete one user via id
		  request=new HttpDelete(resource+"/"+muser.getId().toString());
		  HttpResponse response = httpclient.execute(request); 
		  if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
			  System.out.println("deleting user succeed");  
		  } 
		  else {
			  System.out.println("deleting user failed");   
		  }
		  
		  System.out.println(response.getStatusLine());
		  String rst=EntityUtils.toString(response.getEntity());
          System.out.println(rst);    
	     } 
	 finally {
           httpclient.close();
      }
  }  
}

另外,如果你不想用注解来标注代码,也可以用spring的 xml来配置,就像配置java bean一样,在上面的例子中,在applicatoinContent.xml中,可以写进如下的代码(例子)。

   
    
        
            
        

        
            
            
        

        
            
        

    

JSON-Java API page:

http://stleary.github.io/JSON-java/index.html

使用 TCPMON 这个工具监控以下,可以看到 http body 中只是简单的 json串,没有像 soap 协议那样的“信封”包装

使用 RESTful 设计风格 + 传输 json 数据格式 可以大大的简化 web service 的设计并提高传输效率

其实springMVC也采用了RESTful的设计风格,不过它使用的是spring自己的注解,这些注解和jax-rs中的注解惊奇的类似。如果大家有兴趣可以研究一下springMVC的RESTful特性。


你可能感兴趣的:(web,service,java,Restful)