Spring Boot系列(二) Spring Boot 之 REST
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;
}
Spring Boot系列(二) Spring Boot 之 REST的更多相关文章
- Spring Boot系列二 Spring @Async异步线程池用法总结
1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncT ...
- Spring框架系列(2) - Spring简单例子引入Spring要点
上文中我们简单介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文主要承接上文,向你展示Spring Framework组件 ...
- Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...
- Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计
在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解.本文将帮助你站在设计者的角度去看IOC最顶层的结构设计.@pdai Spring框架系列(6) - Spring IOC实现原理详解 ...
- Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程
上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...
- Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现
前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的.本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所 ...
- Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建
上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor).本文在此基 ...
- Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现
我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理.@pdai Spring框架系列 ...
- Spring框架系列(12) - Spring AOP实现原理详解之JDK代理实现
上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分.@pdai Spring框架系列(12) - Spring AOP实现原理详解 ...
随机推荐
- Nginx+Django-Python+BPMN-JS的整合工作流实战项目
前言 找一个好用的画图工具真心不容易,Activiti 工作流自带的 Web 版画图工具,外表挺华丽,其实使用起来各种拧巴:Eclipse 的 Activiti 画图插件,对于相对复杂的流程也是很不友 ...
- 《你必须掌握的Entity Framework 6.x与Core 2.0》正式出版感想
前言 借书正式出版之际,完整回顾下从写博客到写书整个历程,也算是对自己近三年在技术上的一个总结,整个历程可通过三个万万没想到来概括,请耐心阅读. 写博.写书完整历程回顾 从2013年12月注册博客园账 ...
- Neutron:浮动ip
如果需要从外网直接访问 instance,则可以利用 floating IP. 下面是关于 floating IP 必须知道的事实: 1. floating IP 提供静态 NAT 功能,建立外网 ...
- C#中 SQL语句
SQL语句 SELECT STUFF(( (SELECT ',{' ),)) ),)) ),)) +'}' FROM ZSJTTD_HouseBuilding hb ,,'' ) HouseBuild ...
- es6中常用方法
查询数组中是否包含了某个元素keyword arr.includes(keyword)
- npm 安装包失败 --- 清除npm缓存
今天同事给了一个webpack的项目,我拿过来,npm install 突然出现报错了,并且报了一个奇怪的错误, 如下所示, Unexpected end of JSON input while p ...
- Android List 排序
Collections.sort(list, (l1, l2) -> l1.getID().compareTo(l2.getID())); list:泛型集合 l1:比较的前一个泛型 l2:比较 ...
- mysql学习基础知识3
1.视图 简化sql语句的编写,限制可以查看的数据 一张虚拟的表,不占任何内存,查视图时都是临时从所查的表中拿数据 特点: 对于视图的增删改查 都会同步到原始表 对原始表的修改,会同步到视图内可查看的 ...
- ADRC-active disturbance rejection control-自抗扰控制器
ADRC自抗扰控制基本思想要点: 1.标准型与总扰动,扩张状态与扰动整体辨识,微分信号生成与安排过渡过程以及扰动的消减与控制量产生. ADRC主要构成: 1)跟踪微分器(TD)---the track ...
- 小白在 Eclipse如何避免启动时自动building workspace和validating
问题: Eclipse启动时会出现如下的情况(时间比较长): 原因所在: Validating 意为验证,validating... 逐个的检查每一个文件,Eclipse在启动时自动验证代码和创建wo ...