前言
由于開始要搭建一個java + python的服務,java端提供數(shù)據(jù)庫增刪改查邏輯供python端調(diào)用,第一時間想到了用REST(Representational State Transfer)進行交互
最近這些年,REST已經(jīng)成為web services和APIs的標準架構(gòu),很多APP的架構(gòu)基本上是使用RESTful的形式了。
REST的六個特性:
- Client-Server:服務器端與客戶端分離。
- Stateless(無狀態(tài)):每次客戶端請求必需包含完整的信息,換句話說,每一次請求都是獨立的。
- Cacheable(可緩存):服務器端必需指定哪些請求是可以緩存的。
- Layered System(分層結(jié)構(gòu)):服務器端與客戶端通訊必需標準化,服務器的變更并不會影響客戶端。
- Uniform Interface(統(tǒng)一接口):客戶端與服務器端的通訊方法必需是統(tǒng)一的。
- Code on demand(按需執(zhí)行代碼?):服務器端可以在上下文中執(zhí)行代碼或者腳本?
以下就是我的簡單嘗試
正文
由于REST服務也是一個web服務,所以需要一個servlet容器。
因為主邏輯還是在java端,所以希望這個REST服務非常輕量,選擇一個輕量級的servlet容器很有必要,神馬Tomcat、Resin就太重了,所以鼎鼎大名的 jetty 容器就是非常好的選擇啦
容器選好了,就再考慮用什么RESTful框架實現(xiàn)咯,由于在java6上已經(jīng)有了一套RESTful的api,叫:JAX-RS (Java API for RESTful Web Services),但JAX-RS 的具體實現(xiàn)由第三方提供,例如 Sun 的參考實現(xiàn) Jersey、Apache 的 CXF 以及 JBoss 的 RESTEasy。各項性能比較不錯的是Jersey和RESTEasy,各種百度google一番,最后任性的選擇了Jersey
工具都選好了,開始干正事了,上代碼:
首先配置下maven依賴:
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19.4</version>
</dependency>
<!-- 對象自動轉(zhuǎn)json -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.19.4</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.19.4</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all-server</artifactId>
<version>8.2.0.v20160908</version>
</dependency>
再來寫java代碼:
/**
* Copyright (C) 2017 The RDT of Wireless R&D in MIG. All right reversed. <p/> Created by vellhe on
* 2017/7/7
*/
package com.tencent.awake.data.processing.service.rest;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import com.tencent.awake.data.processing.db.mybatis.dao.model.SubTaskInfoPo;
import com.tencent.awake.data.processing.db.mybatis.dao.model.TaskInfoPo;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import javax.ws.rs.Consumes;
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.core.MediaType;
import java.util.Date;
/**
* @author vellhe@tencent.com
* @date 2017/7/7
* @description 提供REST接口
*/
@Path("/")
public class RestInterface {
/**
* 根據(jù)id查詢?nèi)蝿招畔?
*
* @param id 任務id
* @return 任務信息
*/
@Path("/getTaskInfo/{id}") // 大括號里的是參數(shù)名,在函數(shù)位置使用@PathParam注解映射
@GET // 聲明這個接口必須GET訪問
@Produces(MediaType.APPLICATION_JSON) // 聲明這個接口將以json格式返回
public TaskInfoPo getTaskInfo(@PathParam("id") int id) {
TaskInfoPo taskInfoPo = new TaskInfoPo();
taskInfoPo.setId(id);
taskInfoPo.setAppId("test");
return taskInfoPo;
}
/**
* 根據(jù)taskInfo查詢subTaskInfo.
*
* @param taskInfoPo taskInfo
* @return subTaskInfo
*/
@Path("/getSubTaskInfo/") // url上沒有參數(shù),參數(shù)通過body傳入
@POST
@Consumes(MediaType.APPLICATION_JSON) // 聲明傳入?yún)?shù)是json格式
@Produces(MediaType.APPLICATION_JSON)
public SubTaskInfoPo getSubTaskInfo(TaskInfoPo taskInfoPo) {
SubTaskInfoPo subTaskInfoPo = new SubTaskInfoPo();
subTaskInfoPo.setId((int) System.currentTimeMillis());
subTaskInfoPo.setTaskId(taskInfoPo.getId());
subTaskInfoPo.setCreateTime(new Date());
return subTaskInfoPo;
}
/**
* 測試用的main函數(shù).
*/
public static void main(String[] args) throws Exception {
Server server = new Server(8282); // 監(jiān)聽8282端口
ServletHolder servlet = new ServletHolder(ServletContainer.class);
// 設(shè)置初始化參數(shù)
servlet.setInitParameter("com.sun.jersey.config.property.resourceConfigClass", "com.sun.jersey.api.core.PackagesResourceConfig");
servlet.setInitParameter("com.sun.jersey.config.property.packages", "com.tencent.awake.data.processing");
servlet.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true"); // 自動將對象映射成json返回
ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS);
handler.setContextPath("/");
handler.addServlet(servlet, "/*");
server.setHandler(handler);
server.start();
System.out.println("start...in 8282");
}
}
大部分要說明的東西都在注解里可以找到了,就不一一講解了,運行后會監(jiān)聽8282端口(代碼里),這段demo代碼提供了兩個接口,所以來看看怎么請求這兩個接口吧
我使用PostMan來模擬請求
getTaskInfo

getTaskInfo
getSubTaskInfo

getSubTaskInfo