一.restful
基於jax-rs規範發佈服務使用restful風格的webservice,請求使用的是http協議,可以傳遞xml/json數據。
REST(英文:Representational State Transfer,簡稱REST)描述了一個架構樣式的網絡系統,比如 web 應用程序。它首次出現在 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規範的主要編寫者之一。在目前主流的三種Web服務交互方案中,REST相比於SOAP(Simple Object Access protocol,簡單對象訪問協議)以及XML-RPC更加簡單明瞭,無論是對URL的處理還是對Payload的編碼,REST都傾向於用更加簡單輕量的方法設計和實現。值得注意的是REST並沒有一個明確的標準,而更像是一種設計的風格。
1.restful與非restful
在Restful之前的操作:
http://127.0.0.1/user/query/1 GET 根據用戶id查詢用戶數據
http://127.0.0.1/user/save POST 新增用戶
http://127.0.0.1/user/update POST 修改用戶信息
http://127.0.0.1/user/delete GET/POST 刪除用戶信息
RESTful用法:
http://127.0.0.1/user/1 GET 根據用戶id查詢用戶數據
http://127.0.0.1/user POST 新增用戶
http://127.0.0.1/user PUT 修改用戶信息
http://127.0.0.1/user DELETE 刪除用戶信息
之前的操作是沒有問題的,大神認爲是有問題的,有什麼問題呢?你每次請求的接口或者地址,都在做描述,例如查詢的時候用了query,新增的時候用了save,其實完全沒有這個必要,我使用了get請求,就是查詢.使用post請求,就是新增的請求,我的意圖很明顯,完全沒有必要做描述,這就是爲什麼有了restful.
2.狀態轉化
訪問一個網站,就代表了客戶端和服務器的一個互動過程。在這個過程中,勢必涉及到數據和狀態的變化。互聯網通信協議HTTP協議,是一個無狀態協議。這意味着,所有的狀態都保存在服務器端。因此,如果客戶端想要操作服務器,必須通過某種手段,讓服務器端發生"狀態轉化"(StateTransfer)。而這種轉化是建立在表現層之上的,所以就是"表現層狀態轉化"。客戶端用到的手段,只能是HTTP協議。具體來說,就是HTTP協議裏面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:
POST用來新建資源,
PUT用來更新資源,
DELETE用來刪除資源。
訪問服務器資源,通過不同的http請求方式,服務器就知道對CRUD的哪個操作!
JAX-RS 發佈服務就是使用RESTFUL風格。
二.apache cxf 基於jax-rs規範實現的webservice-服務端
基於jax-rs規範發佈服務使用restful風格的webservice,請求使用的是http協議,可以傳遞xml/json數據。
新建項目:jars-ws-server
1.新建pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>web-service-demo</artifactId>
<groupId>com.meboth.bonc.ljf</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.meboth.bonc.ljf.jars.ws</groupId>
<artifactId>jars-ws-server</artifactId>
<version>1.0-SNAPSHOT</version>
<name>jars-ws-server</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- jaxrs 支持包 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 內置的jetty服務器 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<!-- 客戶端調用時候使用的包(WebClient工具類調用服務端) -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 基於restful風格的webservice,客戶端與服務端之間可以傳遞json,這個就是json支持相關包 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
2.定義實體類
package com.meboth.bonc.ljf.jars.ws.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "myBike")
public class Bike {
private int id;
private String carName;
private float price;
public Bike() {
}
public Bike(int id, String carName, float price) {
this.id = id;
this.carName = carName;
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
package com.meboth.bonc.ljf.jars.ws.model;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
@XmlRootElement(name = "myPeople")
public class People {
private int id;
private String userName;
private List<Bike> bikeList=new ArrayList<Bike>();
public People() {
}
public People(int id, String userName, List<Bike> bikeList) {
this.id = id;
this.userName = userName;
this.bikeList = bikeList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<Bike> getBikeList() {
return bikeList;
}
public void setBikeList(List<Bike> bikeList) {
this.bikeList = bikeList;
}
}
3.定義實現類
package com.meboth.bonc.ljf.jars.ws.service;
import com.meboth.bonc.ljf.jars.ws.model.People;
import javax.ws.rs.*;
import java.util.List;
@Path("/tjService") // 路徑;訪問當前服務接口時候的路徑。
@Produces("*/*")
public interface TianJingService {
@POST
@Path("/tjUser") // 路徑; 訪問當前服務接口的方法路徑
// @Consumes 服務端支持的請求的數據格式(xml、json)
@Consumes({ "application/xml", "application/json" })
public void saveUser(People user);
@PUT
@Path("/tjUser")
@Consumes({ "application/xml", "application/json" })
public void updateUser(People user);
@GET
@Path("/tjUser")
// @Produces 服務端支持的響應的數據格式
@Produces({ "application/xml", "application/json" })
public List<People> findAllUsers();
@GET
@Path("/tjUser/{id}")
@Consumes("application/xml")
@Produces({ "application/xml", "application/json" })
public People finUserById(@PathParam("id") Integer id);
@DELETE
@Path("/tjUser/{id}")
@Consumes({"application/xml", "application/json"})
public void deleteUser(@PathParam("id") Integer id);
}
package com.meboth.bonc.ljf.jars.ws.service;
import com.meboth.bonc.ljf.jars.ws.model.Bike;
import com.meboth.bonc.ljf.jars.ws.model.People;
import java.util.ArrayList;
import java.util.List;
public class TianJingServiceImpl implements TianJingService {
public void saveUser(People user) {
System.out.println("save user:" + user.getUserName());
}
public void updateUser(People user) {
System.out.println("update user:" + user);
}
public List<People> findAllUsers() {
List<People> users = new ArrayList<People>();
// 汽車
List<Bike> carList1 = new ArrayList<Bike>();
Bike car1 = new Bike(101,"保時捷",1000000f);
Bike car2 = new Bike(102,"林肯",400000f);
carList1.add(car1);
carList1.add(car2);
// 用戶
People user1 = new People(1,"小明",carList1);
People user2 = new People(2,"小麗",carList1);
// 用戶集合
users.add(user1);
users.add(user2);
return users;
}
public People finUserById(Integer id) {
if (id == 1) {
Bike bike= new Bike(101,"保時捷",1000000f);
List<Bike> bList= new ArrayList<Bike>();
bList.add(bike);
return new People(1,"小明",bList);
}
return null;
}
public void deleteUser(Integer id) {
System.out.println("delete user id :" + id);
}
}
使用的註解:
@XmlRootElement
指定根元素,
作用:客戶端與服務端傳遞對象數據時候,序列化爲xml或json的根元素的名稱
@Path("/userService")
路徑;訪問當前服務接口時候的路徑、接口方法的路徑。
@POST insert操作
@PUT update操作
@GET select 查詢操作
@DELETE delete刪除操作
@Consumes 服務端支持的請求的數據格式(xml、json)
@Produces 服務端支持的響應的數據格式
4.資源配置類:
log4j.rootLogger=INFO,console,FILE
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.threshold=INFO
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}[%5p]-%c(%L)-%m%n
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.Append=true
log4j.appender.FILE.File=./web-service.log
log4j.appender.FILE.Threshold=INFO
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-ddHH:mm:ss}[%5p]-%c(%L)-%m%n
log4j.appender.FILE.MaxFileSize=30MB
5.啓動類
package com.meboth.bonc.ljf.jars.ws;
import com.meboth.bonc.ljf.jars.ws.service.TianJingServiceImpl;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
/**
* Hello world!
*
*/
public class JaxRsServer
{
/**
* 發佈restful風格的webservice的服務
*/
public static void main( String[] args ) {
//1.創建服務工廠
JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
//2.設置服務地址、
factory.setAddress("http://localhost:8001/rs");
//3.實例化服務類、
factory.setServiceBean(new TianJingServiceImpl());
// 添加日誌攔截器
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
//4.創建服務
factory.create();
System.out.println("發佈服務成功.......端口:8001");
}
}
6.啓動服務
三.apache cxf 基於jax-rs規範實現的webservice-客戶端
新建項目:jars-ws-client
1.pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>web-service-demo</artifactId>
<groupId>com.meboth.bonc.ljf</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.meboth.bonc.ljf.jars.ws.client</groupId>
<artifactId>jars-ws-client</artifactId>
<version>1.0-SNAPSHOT</version>
<name>jars-ws-client</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- jaxrs 支持包 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 內置的jetty服務器 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<!-- 客戶端調用時候使用的包(WebClient工具類調用服務端) -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.0.1</version>
</dependency>
<!-- 基於restful風格的webservice,客戶端與服務端之間可以傳遞json,這個就是json支持相關包 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- maven的jdk編譯插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
2.實體類:
package com.meboth.bonc.ljf.jars.ws.client.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "myBike")
public class Bike {
private int id;
private String carName;
private float price;
public Bike() {
}
public Bike(int id, String carName, float price) {
this.id = id;
this.carName = carName;
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
package com.meboth.bonc.ljf.jars.ws.client.model;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
@XmlRootElement(name = "myPeople")
public class People {
private int id;
private String userName;
private List<Bike> bikeList=new ArrayList<Bike>();
public People() {
}
public People(int id, String userName, List<Bike> bikeList) {
this.id = id;
this.userName = userName;
this.bikeList = bikeList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<Bike> getBikeList() {
return bikeList;
}
public void setBikeList(List<Bike> bikeList) {
this.bikeList = bikeList;
}
}
3.啓動類:
package com.meboth.bonc.ljf.jars.ws.client;
import com.meboth.bonc.ljf.jars.ws.client.model.Bike;
import com.meboth.bonc.ljf.jars.ws.client.model.People;
import org.apache.cxf.jaxrs.client.WebClient;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class JarWsClient {
/**
* .create() 指定服務端地址
.type() 指定請求數據格式(xml、json)
.accept() 指定響應數據格式
.post()/put()/delete()/get() 指定請求類型
*/
public static void main(String args[])throws Exception{
//save();
//update();
//findOne();
findAll();
}
/**
* 添加
* @throws Exception
*/
public static void save() throws Exception {
// 基於restful風格的webservice開發的客戶端調用,直接通過一個類:WebClient類完成
Bike bike= new Bike(101,"haval h6",1000000f);
List<Bike> bList= new ArrayList<Bike>();
bList.add(bike);
bList.add(new Bike(101,"linken",3000000f));
WebClient.create("http://localhost:8001/rs/tjService/tjUser") // 地址
.type(MediaType.APPLICATION_JSON) // 請求數據格式是json
.post(new People(100,"Kobe",bList)); // 發送請求的類型
}
/**
* 修改
* @throws Exception
*/
public static void update() throws Exception {
WebClient.create("http://localhost:8001/rs/tjService/tjUser") // 地址
.type(MediaType.APPLICATION_JSON) // 請求數據格式是json
.put(new People(100,"Kobe",null)); // 發送請求的類型
}
/**
* 通過id查找
* @throws Exception
*/
public static void findOne() throws Exception {
People user =
WebClient
.create("http://localhost:8001/rs/tjService/tjUser/1") // 地址
.accept(MediaType.APPLICATION_JSON) // 響應的數據格式
.get(People.class);
System.out.println(user);
}
/**
* 查詢全部
* @throws Exception
*/
public static void findAll() throws Exception {
Collection<? extends People> collection =
WebClient
.create("http://localhost:8001/rs/tjService/tjUser/")
.accept(MediaType.APPLICATION_JSON)
.getCollection(People.class);
System.out.println(collection);
}
}
5.log4j日誌:
log4j.rootLogger=INFO,console,FILE
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.threshold=INFO
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}[%5p]-%c(%L)-%m%n
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.Append=true
log4j.appender.FILE.File=./web-service.log
log4j.appender.FILE.Threshold=INFO
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-ddHH:mm:ss}[%5p]-%c(%L)-%m%n
log4j.appender.FILE.MaxFileSize=30MB
6.調試訪問:
執行findAll()方法
public static void main(String args[])throws Exception{ //save(); //update(); //findOne(); findAll(); }