REST简介
Rest(Representational State Transfer),表属性性状态转移,Rest是为分布式媒体系统设计的一种架构风格,而不是标准。所谓的Rest架构,指的是其设计风格Rest,但是其视图解析、印射可能还是MVC。
传统的Web应用大都是B/S架构,它包括了如下一些规范
- 客户/服务器模型(Client-Server)
- 无状态(Stateless)
- 缓存(Cache)
为了适应Rest风格,新增三个新的规范
- 统一接口(Uniform Interface)
- 分层系统(Layered System)
- 按需代码(Code-On-Demand),可选规范
REST架构是针对Web应用而设计的,其目的是为了降低开发的复杂性,提高系统的可伸缩性。REST提出了如下设计准则
- 网络上的所有事物都被抽象为资源(resource)
- 每个资源对应一个唯一的资源标识符(resource identifier)
- 通过通用的连接器接口(generic connector interface)对资源进行操作
- 对资源的各种操作不会改变资源标识符
- 所有的操作都是无状态的(stateless)
SpringBoot 搭建REST
pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>zl</groupId>
<artifactId>example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>rest</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- jsonpath支持-->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<!-- 热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
HttpClient 访问REST
HTTP访问
controller
package zl.example.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
@RestController
@RequestMapping
public class BookController {
private static Map<Integer, JSONObject> books = new HashMap<>();
@RequestMapping(value="/books",method=RequestMethod.GET)
public JSONObject list(String name) {
JSONObject j = new JSONObject();
j.put("status", true);
j.put("message", "success");
j.put("books",books.values());
return j;
}
@RequestMapping(value="/books/{id}",method=RequestMethod.PUT)
public JSONObject update(@PathVariable("id")Integer id,String name) {
JSONObject j = new JSONObject();
j.put("status", true);
j.put("message", "success");
JSONObject book = books.get(id);
if (book != null) {
book.replace("name", name);
}
j.put("book", book);
return j;
}
@RequestMapping(value="/books/{id}",method=RequestMethod.DELETE)
public JSONObject delete(@PathVariable(value="id")Integer id) {
JSONObject j = new JSONObject();
j.put("status", true);
j.put("message", "success");
books.remove(id);
return j;
}
@RequestMapping(value="/books",method=RequestMethod.POST)
public JSONObject add(Integer id,String name) {
JSONObject j = new JSONObject();
j.put("status", true);
j.put("message", "success");
JSONObject book = new JSONObject();
book.put("id", id);
book.put("name",name);
books.put(id, book);
return j;
}
}
test
package zl.example;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RestApplicationTests {
private CloseableHttpClient httpClient;
@Before
public void init() {
httpClient = HttpClients.createDefault();
}
@After
public void end() {
try {
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void doPost() {
String uri = "http://localhost:90/books";
HttpPost post = new HttpPost(uri);
// 拼接参数..
List<NameValuePair> kvList = new ArrayList<>();
kvList.add(new BasicNameValuePair("id", "1"));
kvList.add(new BasicNameValuePair("name", "java"));
CloseableHttpResponse response = null;
try {
StringEntity param = new UrlEncodedFormEntity(kvList, "utf-8");
post.setEntity(param);
post.setHeader("Content-type", "application/x-www-form-urlencoded");
response = httpClient.execute(post);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String string = EntityUtils.toString(entity, "utf-8");
if (statusCode != HttpStatus.SC_OK) {
System.out.println("error:" + string);
}
System.out.println("###doPost###");
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void doGet() {
String uri = "http://localhost:90/books";
// 拼接参数..
HttpGet get = new HttpGet(uri);
/*
* RequestConfig config = RequestConfig.DEFAULT; get.setConfig(config);
*/
CloseableHttpResponse response = null;
try {
response = httpClient.execute(get);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String string = EntityUtils.toString(entity, "utf-8");
if (statusCode != HttpStatus.SC_OK) {
System.out.println("error:" + string);
}
System.out.println("###doGet###");
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void doPut() {
String uri = "http://localhost:90/books/1";
HttpPut put = new HttpPut(uri);
// 拼接参数..
List<NameValuePair> kvList = new ArrayList<>();
kvList.add(new BasicNameValuePair("name", "python"));
CloseableHttpResponse response = null;
try {
StringEntity param = new UrlEncodedFormEntity(kvList, "utf-8");
put.setEntity(param);
put.setHeader("Content-type", "application/x-www-form-urlencoded");
response = httpClient.execute(put);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String string = EntityUtils.toString(entity, "utf-8");
if (statusCode != HttpStatus.SC_OK) {
System.out.println("error:" + string);
}
System.out.println("###doPut###");
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void doDelete() {
String uri = "http://localhost:90/books/1";
HttpDelete delete = new HttpDelete(uri);
// delete不传递参数
CloseableHttpResponse response = null;
try {
response = httpClient.execute(delete);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
String string = EntityUtils.toString(entity, "utf-8");
if (statusCode != HttpStatus.SC_OK) {
System.out.println("error:" + string);
}
System.out.println("###doDelete###");
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
HTTPS访问
项目要使用https,需要进行改造。
生成SSL证书(window)
keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
keytool -genkey命令说明(密钥密码在命令执行时指定,此处指定test08)
- alias 证书别名
- keyalg 密钥算法
- keystore 证书存储位置和文件名
- keysize 密钥长度
- validity 证书有效期天数
springboot配置
server:
port: 90
ssl:
key-store: classpath:keystore.p12
key-store-password: test08
key-store-type: PKCS12
key-alias: tomcat
test
@Before
public void init() {
SSLContext sslContext;
try {
sslContext = SSLContexts.custom()
.loadTrustMaterial(null, (chain,authType)->true)
.setProtocol("TLSv1.2").build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,(hostname,sslsession)->true);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
.build();
} catch (Exception e) {
e.printStackTrace();
}
}
将uri的http,改为https即可
初识REST: https://www.jianshu.com/p/50323a08edbc
SpringBoot REST: https://spring.io/guides/gs/rest-service/