Rest (Representational Stat Transer) 是一种软件架构风格.
基础理论
架构特性
- 性能
- 可伸缩
- 简化的统一接口
- 按需修改
- 组件通信透明
- 可移植
- 可靠性
架构约束
- C/S 结构
- 无状态: Stateless
- 可缓存
- 分层系统
- 按需编码
- 统一接口: URI , 自描述消息(MIME),超媒体作为应用状态引擎(HATEOAS)
WEB MVC
MVC 中 URL 与 HTTP 方法的联系
URL 和 HTTP 方法存在联系. 不同方法对应的不同状态, 比如: https://api.exaple.com/resources/
使用GET方法为查询, PUT为替换文件, POST为创建,DELETE 为删除.
其中GET请求为安全方法, 多次请求结果一致. POST 为非幂等请求, 多次提交会创建多个, DELETE,PUT为幂等请求. 幂等性是服务端的实现, 符合幂等性的方法实现更安全.
MVC 中的媒体类型MIME
通过请求头中的Accept获取媒体类型
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
下面的方法用来添加默认的消息转化器:
org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.addDefaultHttpMessageConverters()
对于json, 可以找到转化器名称为MappingJackson2HttpMessageConverter
, 其中(可能是父类)定义的 read()
和 write()
方法用来读写数据.
同时也要注意canRead()
和 canWrite()
方法, 在相关的processor中, 通过遍历MessageConverters的List并调用can*
方法来确定是否应用消息转化器, 找到第一个匹配的就停止遍历了. 因此消息转化器的顺序至关重要.
自定义MessageConverter
- 扩展
AbstractHttpMessageConverter
抽象类, 并实现其中方法
public class PropertiesPersonHttpMessageConverter extends AbstractHttpMessageConverter<Person> {
public PropertiesPersonHttpMessageConverter(){
super(MediaType.valueOf("application/properties+person"));
setDefaultCharset(Charset.forName("UTF-8"));
}
@Override
protected boolean supports(Class<?> aClass) {
return aClass.isAssignableFrom(Person.class);
}
@Override
protected Person readInternal(Class<? extends Person> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
InputStream inputStream = httpInputMessage.getBody();
Properties properties = new Properties();
properties.load(new InputStreamReader(inputStream,getDefaultCharset()));
Person person = new Person(Integer.valueOf(properties.get("person.id").toString()) ,properties.get("person.name").toString());
return person;
}
@Override
protected void writeInternal(Person person, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
OutputStream outputStream = httpOutputMessage.getBody();
Properties properties = new Properties();
properties.setProperty("person.id",String.valueOf(person.getId()) );
properties.setProperty("person.name",person.getName());
properties.store(new OutputStreamWriter(outputStream,getDefaultCharset()),"person to properties");
}
}
- 添加配置并将自定义的消息转化器添加到列表实现接口
WebMvcConfigurer
实现方法extendMessageConverters()
@Configuration
public class MyConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2XmlHttpMessageConverter());
converters.add(new PropertiesPersonHttpMessageConverter());
}
}
- 在controller的方法上添加
@PostMapping(produces="application/my+format)
这个produers对应header的Accept
. 是我们自定义的MIME格式.
@PostMapping(value="/persontoproperties",
produces = "application/properties+person",
consumes = "application/json"
)
public Person person2Properties(@RequestBody(required = false) Person person){
return person==null?new Person(0,"default"):person;
}