1. RESTful简述
    REST是一种设计风格,是一组约束条件及原则,而遵循REST风格的架构就称为RESTful架构,资源是RESTful的核心,一个好的RESTful架构,通过URL就能很清晰的了解其相应的操作和需求是什么,即
1. 通过URL定位资源,如:
com.mobin/api/v1/shenzhen/subways //获取深圳地铁列表
com.mobin/api/v1/shenzhen/schools   //获取深圳学校列表
2. HTTP描述操作
GET:获取资源
POST:创建资源
PUT:更新资源
DELETE:删除资源
如:
GET com.mobin/api/v1/shenzhen/subways/1:获取ID为1的地铁信息
请求的资源通常都以JSON或XML等返回给Client,使用RESTful架构只需在Sever端提供一套RESTful API便能在web、IOS、Android共用
API设计是个很讲究的事情,可以参考GitHub的API设计规范

2. SpringBoot集成MyBatis
 1. 将xxxMapper.xml及sqlMapConfig.xml放入resource对应目录
 2. application.properties加载MyBatis配置文件及配置数据源

 ##application.properties
#加载mybatis配置文件
mybatis.mapper-locations = classpath:mapper/*Mapper.xml
mybatis.config-location = classpath:mapper/config/sqlMapConfig.xml

#指定别名
mybatis.type-aliases-package = com.mobin.entity

#数据源
spring.datasource.url = jdbc:postgresql://localhost:5432/xxx
spring.datasource.driver-class-name = org.postgresql.Driver
spring.datasource.username = postgres
spring.datasource.password = xxxx

MyBatis 3之后官方提供了特定的API来的支持动态SQL,可以使用注解+Java代码来替代XML,但是复杂的SQL语句还是走XML的方式,XML更直观(其实也恶心),注解的方式对于代码的侵入太严重,修改后还需要重新编译。

3. 日志配置
     Spring boot默认的日志框架为Logback,配置起来相当友好具有更好的性能,还可以对指定的服务的日志进行不同级别的过滤并不影响其他服务日志的级别
1. 控制台日志配置
2. 开发、测试、生产环境的配置

 ##logbcak-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<contextName>${appname}</contextName>
<!--控制台日志配置-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]%-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>

<appender name="FILEPROD" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>SpringBootRESTful.%d{yyyy-MM-dd}.log</FileNamePattern>
<!-- 日志保留天数-->
<MaxHistory>20</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]%-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>

<appender name="FILETEST" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>test.SpringBootRESTful.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>20</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]%-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>

<!--开发环境的日志配置 -->
<springProfile name="dev">
<!--开发环境通常会对指定包或类进行测试 -->
<logger name="com.mobin.dao" level="DEBUG">
<appender-ref ref="STDOUT"/>
</logger>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</springProfile>

<!--测试环境的日志配置 -->
<springProfile name="test">
<root level="DEBUG">
<appender-ref ref="FILETEST"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>

<!--生产环境的日志配置 -->
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="FILEINFO"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
</configuration>

4. 异常处理
4.1 在API设计规范中,对异常的处理至少是
 1. 返回相应的错误代码
 2. 返回相应的错误描述
 3. 对应的资源模块
4.2 使用@RestControllerAdvice定义全局异常处理
@RestControllerAdvice是Spring 4.3之后的新特性,其相当于@ControllerAdvice+ResponseBody,所以使用@RestControllerAdvice可以将错误信息以Json的格式返回
1. 自定义异常类

 ##com.mobin.exception.EntityNotFoundException
//当请求的资源不存在时抛出该异常
public class EntityNotFoundException extends RuntimeException{
public EntityNotFoundException(String mes){
super(mes);
}
}

2. 定义全局异常类

 ##com.mobin.exception.GlobalExceptionHadlerActice
@RestControllerAdvice
public class GlobalExceptionHadlerActice {
private static final long serialVersionUID = 1L;
@ExceptionHandler(value = EntityNotFoundException.class)
public ErrorMessage entityNotFoundException(HttpServletRequest request, Exception e){
ErrorMessage errorMessage = new ErrorMessage();
errorMessage.setStatus(HttpStatus.NOT_FOUND.value());
errorMessage.setMessage(e.getLocalizedMessage());
errorMessage.setUrl(request.getRequestURL().toString());
return errorMessage;
}
}

ErrorMessage为自定义的实体类,包含statusCode,message及url字段。

3. 相应的请求方法

 ## com.mobin.controller.SubwayController
@RequestMapping(value="/{id}",method = RequestMethod.GET )
public SubwayResult<Subway> getSubwayByID(@PathVariable Integer id) {
SubwayResult<Subway> result = new SubwayResult();
Subway subway = subwayService.findSubwayByID(id);
if (subway == null){
throw new EntityNotFoundException("资源不存在");
}
result.setStatus(HttpStatus.OK.value());
result.setData(subway);
return result;
}

4. 通过curl进行测试

 MOBIN:~ mobin$ curl -XGET -w "\n" 'localhost:8089/api/subways/1999'
{
"message":"资源不存在",
"status":404,
"url":"http://localhost:8089/api/subways/1999"
}

5. 使用fastjson
1.  引入fastJson依赖
2. 自定义WebMvcConfigurer并继承WebMvcConfigurerAdapter
3. 重写configureMessageConverters方法
4. 自定义配置FastJsonConfig
5. 将FastJsonHttpMessageConverter添加到HttpMessageConverter
相应代码:

 ##com.mobin.config.WebMvcConfigurer
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter{
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty,
SerializerFeature.WriteNullBooleanAsFalse,
SerializerFeature.PrettyFormat);
converter.setDateFormat("yyyy-MM-dd HH:mm:ss");
converter.setFastJsonConfig(config);
converters.add(converter);
}
}

SerializerFeature.WriteNullListAsEmpty:List类型字段为null时输出[]而非null
SerializerFeature.WriteMapNullValue:显示空字段
SerializerFeature.WriteNullStringAsEmpty:字符串类型字段为null时间输出""而非null
SerializerFeature.WriteNullBooleanAsFalse:Boolean类型字段为null时输出false而null
SerializerFeature.PrettyFormat:美化json输出,否则会作为整行输出

解决浏览器中返回json显示乱码问题(参考自:http://blog.csdn.net/kingboyworld/article/details/70068676

##application.properties
spring.http.encoding.charset=UTF-8
spring.http.encoding.enable=true
spring.http.encoding.force=true

6. 使用PageHelper进行分页
      分页使用的是PageHelper插件,基本原理就是在Executor及mappedStatement之间对SQL语句进行拦截并对SQL添加相应的分页操作再封装传递给mappedStatement,该插件支持单表及多表的分页,使用方便,只需在SQL执行语句前加上一条分布代码即可(通常是在server层),想想如果是手动的设置SQL语句的limit和offset,分页场景一旦多了就特别恶心,即便配合MyBatis的逆向工程也是。
1. 引入Spring boot对应的PageHelper依赖
2. 在application.properties配置PageHelper
3. 在指定的SQL语句前添加分页代码

 ##application.properties
#指定数据库方言
pagehelper.helperDialect=postgresql
#pageNum<=0时返回第一页数据,pageNum超过总页数时返回最后一页数据
pagehelper.reasonable=true

相应代码:

 ##com.mobin.service.impl.SubwayServiceImpl
public List<Subway> findSubways(int pageNum,int pageSize){
//第三个参数为fales时表示不对表进行count操作
PageHelper.startPage(pageNum,pageSize,false);
return subwayMapper.findSubways();
}

项目地址:

https://github.com/MOBIN-F/SpringBootRESTful

参考资料:

GitHub API

How to use @RestControllerAdvice for handling Exception with RestfulApi

PageHelper使用方法

SerializerFeature使用详解

logback相关配置

基于Spring Boot的RESTful API实践(一)的更多相关文章

  1. 使用 Spring Boot 构建 RESTful API

    1. 使用 Idea 创建 Spring Initializer 项目 在创建项目的对话框中添加 Web 和 Lombok,或者建立项目后在 pom.xml 中添加依赖: <dependency ...

  2. Spring Boot中Restful Api的异常统一处理

    我们在用Spring Boot去向前端提供Restful Api接口时,经常会遇到接口处理异常的情况,产生异常的可能原因是参数错误,空指针异常,SQL执行错误等等. 当发生这些异常时,Spring B ...

  3. Spring Boot构建RESTful API与单元测试

    如果您对Spring MVC不熟悉并且还没有尝试过快速入门案例,建议先看一下相关的内容. @Controller:修饰class,用来创建处理http请求的对象 @RestController:Spr ...

  4. 用Kotlin写一个基于Spring Boot的RESTful服务

    Spring太复杂了,配置这个东西简直就是浪费生命.尤其在没有什么并发压力,随便搞一个RESTful服务 让整个业务跑起来先的情况下,更是么有必要纠结在一堆的XML配置上.显然这么想的人是很多的,于是 ...

  5. Spring Boot构建RESTful API

    @Controller:修饰class,用来创建处理http请求的对象 @RestController:Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseB ...

  6. 通过spring boot提供restful api

    1 将返回设置为produces = "application/json" 返回给客户端json格式的response. 2 对各种异常的处理 各种异常如何返回给客户端? 各种异常 ...

  7. 基于Spring Boot、Spring Cloud、Docker的微服务系统架构实践

    由于最近公司业务需要,需要搭建基于Spring Cloud的微服务系统.遍访各大搜索引擎,发现国内资料少之又少,也难怪,国内Dubbo正统治着天下.但是,一个技术总有它的瓶颈,Dubbo也有它捉襟见肘 ...

  8. 基于spring boot 2.x 的 spring-cloud-admin 实践

    spring cloud admin 简介 Spring Boot Admin 用于监控基于 Spring Boot 的应用,它是在 Spring Boot Actuator 的基础上提供简洁的可视化 ...

  9. 基于Spring Boot和Spring Cloud实现微服务架构学习

    转载自:http://blog.csdn.net/enweitech/article/details/52582918 看了几周Spring相关框架的书籍和官方demo,是时候开始总结下这中间的学习感 ...

随机推荐

  1. BZOJ 1935: [Shoi2007]Tree 园丁的烦恼 [树状数组 离线 离散化]

    传送门 刚才我还在郁闷网上怎么没人用$CDQ$分治做 突然发现根本没有时间序.... #include<iostream> #include<cstdio> #include& ...

  2. Orleans例子源码

    这是Orleans系列文章中的一篇.首篇文章在此 我共享以下我现在写教程的简单的Orleans例子源码. 这个代码已经是我为了写word改动过了的.不过大体内容是通用的. 我写博客总体想法是:去除所有 ...

  3. SQL Server 文件操作

    在master数据库中,SQL Server提供系统扩展的存储过程,其中有一些存储过程的命名以xp_开头,用于处理操作系统的文件. 一,判断文件是否存在 存储过程sys.xp_fileexist 用于 ...

  4. Mysql大数据备份和增量备份及还原

    目前主流的有两个工具可以实现物理热备:ibbackup和xtrabackup ;ibbackup是需要授权价格昂贵,而xtrabackup功能比ibbackup强大而且是开源的 Xtrabackup提 ...

  5. 炸金花的JS实现从0开始之 -------现在什么都不会(1)

    新年结束了.回想起来唯一留下乐趣的就是在家和朋友玩玩炸金花. 遂有此文. 对不起,我这时候还没有思路. 让我捋一捋. ... ... 捋一捋啊... ... 好了.今天先这样吧: (1)先整理出所有的 ...

  6. linux、windows系统间传输文件

    日常工作中经常涉及到系统间的文件传输,下面就简单说一下常用的方法   linux--windows      工具:winscp.SecureCRT.Zmodem(sz, rz)   linux--l ...

  7. Spring 依赖注入的理解

    首先: 1.依赖注入就是一种在一个需要使用它的类中定义一个接口,该类中不管这个接口是怎么实现的,只是执行这个方法 2.依赖注入可以让该类实现通用 代码: 1.定义一个饮料接口 package cn.l ...

  8. 几种优化ajax的执行速度的方法

    1.尽量使用局部的变量,而不使用全局变量: 2.优化for循环 3.尽量少用eval,每次使用eval都需要消耗大量的时间: 4.将DOM节点放在文档上. 5.尽量减少点好(.)操作符号的使用

  9. python中重要的模块--asyncio

    一直对asyncio这个库比较感兴趣,毕竟这是官网也非常推荐的一个实现高并发的一个模块,python也是在python 3.4中引入了协程的概念.也通过这次整理更加深刻理解这个模块的使用 asynci ...

  10. Android动态加载技术(插件化技术)

    No1: 插件化技术的好处: 1)减轻应用的内存和CPU占用 2)实现热插拔,即在不发布新版本的情况下更新某些模块 No2: 插件化方案必须要解决三个基础性问题:资源访问.Activity生命周期的管 ...