基於Spring Boot的RESTful API實踐(一)

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設計規範java

2. SpringBoot集成MyBatis
 1. 將xxxMapper.xml及sqlMapConfig.xml放入resource對應目錄
 2. application.properties加載MyBatis配置文件及配置數據源git

 1 ##application.properties
 2 #加載mybatis配置文件
 3 mybatis.mapper-locations = classpath:mapper/*Mapper.xml
 4 mybatis.config-location = classpath:mapper/config/sqlMapConfig.xml
 5  6 #指定別名
 7 mybatis.type-aliases-package = com.mobin.entity
 8  9 #數據源
10 spring.datasource.url = jdbc:postgresql://localhost:5432/xxx
11 spring.datasource.driver-class-name = org.postgresql.Driver
12 spring.datasource.username = postgres
13 spring.datasource.password = xxxx

MyBatis 3以後官方提供了特定的API來的支持動態SQL,可使用註解+Java代碼來替代XML,可是複雜的SQL語句仍是走XML的方式,XML更直觀(其實也噁心),註解的方式對於代碼的侵入太嚴重,修改後還須要從新編譯。github

3. 日誌配置
     Spring boot默認的日誌框架爲Logback,配置起來至關友好具備更好的性能,還能夠對指定的服務的日誌進行不一樣級別的過濾並不影響其餘服務日誌的級別
1. 控制檯日誌配置
2. 開發、測試、生產環境的配置web

 1 ##logbcak-spring.xml
 2 <?xml version="1.0" encoding="UTF-8"?>
 3 <configuration debug="false">
 4    <contextName>${appname}</contextName>
 5    <!--控制檯日誌配置-->
 6    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 7    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
 8    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]%-5level %logger{50} - %msg%n</pattern>
 9    </encoder>
10    </appender>
11 12    <appender name="FILEPROD" class="ch.qos.logback.core.rolling.RollingFileAppender">
13        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
14        <FileNamePattern>SpringBootRESTful.%d{yyyy-MM-dd}.log</FileNamePattern>
15        <!-- 日誌保留天數-->
16        <MaxHistory>20</MaxHistory>
17        </rollingPolicy>
18        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
19            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]%-5level %logger{50} - %msg%n</pattern>
20        </encoder>
21    </appender>
22 23    <appender name="FILETEST" class="ch.qos.logback.core.rolling.RollingFileAppender">
24        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
25            <FileNamePattern>test.SpringBootRESTful.%d{yyyy-MM-dd}.log</FileNamePattern>
26            <MaxHistory>20</MaxHistory>
27        </rollingPolicy>
28        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
29            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]%-5level %logger{50} - %msg%n</pattern>
30        </encoder>
31    </appender>
32 33    <!--開發環境的日誌配置 -->
34    <springProfile name="dev">
35        <!--開發環境一般會對指定包或類進行測試 -->
36        <logger name="com.mobin.dao" level="DEBUG">
37            <appender-ref ref="STDOUT"/>
38        </logger>
39        <root level="INFO">
40            <appender-ref ref="STDOUT"/>
41        </root>
42    </springProfile>
43 44    <!--測試環境的日誌配置 -->
45    <springProfile name="test">
46        <root level="DEBUG">
47            <appender-ref ref="FILETEST"/>
48            <appender-ref ref="STDOUT"/>
49        </root>
50    </springProfile>
51 52    <!--生產環境的日誌配置 -->
53    <springProfile name="prod">
54        <root level="INFO">
55            <appender-ref ref="FILEINFO"/>
56            <appender-ref ref="STDOUT"/>
57        </root>
58    </springProfile>
59 </configuration>

4. 異常處理
4.1 在API設計規範中,對異常的處理至少是
 1. 返回相應的錯誤代碼
 2. 返回相應的錯誤描述
 3. 對應的資源模塊
4.2 使用@RestControllerAdvice定義全局異常處理
@RestControllerAdvice是Spring 4.3以後的新特性,其至關於@ControllerAdvice+ResponseBody,因此使用@RestControllerAdvice能夠將錯誤信息以Json的格式返回
1. 自定義異常類spring

1 ##com.mobin.exception.EntityNotFoundException
2 //當請求的資源不存在時拋出該異常
3 public class EntityNotFoundException extends RuntimeException{
4    public EntityNotFoundException(String mes){
5      super(mes);
6   }
7 }

2. 定義全局異常類sql

 1 ##com.mobin.exception.GlobalExceptionHadlerActice
 2 @RestControllerAdvice
 3 public class GlobalExceptionHadlerActice {
 4    private static final long serialVersionUID = 1L;
 5    @ExceptionHandler(value = EntityNotFoundException.class)
 6    public ErrorMessage entityNotFoundException(HttpServletRequest request, Exception e){
 7        ErrorMessage errorMessage = new ErrorMessage();
 8        errorMessage.setStatus(HttpStatus.NOT_FOUND.value());
 9        errorMessage.setMessage(e.getLocalizedMessage());
10        errorMessage.setUrl(request.getRequestURL().toString());
11        return errorMessage;
12   }
13 }

ErrorMessage爲自定義的實體類,包含statusCode,message及url字段。數據庫

3. 相應的請求方法json

 1 ## com.mobin.controller.SubwayController
 2 @RequestMapping(value="/{id}",method = RequestMethod.GET )
 3    public SubwayResult<Subway> getSubwayByID(@PathVariable Integer id) {
 4        SubwayResult<Subway> result = new SubwayResult();
 5        Subway subway = subwayService.findSubwayByID(id);
 6        if (subway == null){
 7            throw new EntityNotFoundException("資源不存在");
 8       }
 9        result.setStatus(HttpStatus.OK.value());
10        result.setData(subway);
11        return result;
12   }

4. 經過curl進行測試api

1 MOBIN:~ mobin$ curl -XGET -w "\n" 'localhost:8089/api/subways/1999'
2 {
3     "message":"資源不存在",
4     "status":404,
5     "url":"http://localhost:8089/api/subways/1999"
6 }

5. 使用fastjson
1.  引入fastJson依賴
2. 自定義WebMvcConfigurer並繼承WebMvcConfigurerAdapter
3. 重寫configureMessageConverters方法
4. 自定義配置FastJsonConfig
5. 將FastJsonHttpMessageConverter添加到HttpMessageConverter
相應代碼:瀏覽器

 1 ##com.mobin.config.WebMvcConfigurer
 2 @Configuration
 3 public class WebMvcConfigurer extends WebMvcConfigurerAdapter{
 4    @Override
 5    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
 6        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
 7        FastJsonConfig config = new FastJsonConfig();
 8        config.setSerializerFeatures(SerializerFeature.WriteNullListAsEmpty,
 9                SerializerFeature.WriteMapNullValue,
10                SerializerFeature.WriteNullStringAsEmpty,
11                SerializerFeature.WriteNullBooleanAsFalse,
12                SerializerFeature.PrettyFormat);
13        converter.setDateFormat("yyyy-MM-dd HH:mm:ss");
14        converter.setFastJsonConfig(config);
15        converters.add(converter);
1617   }
18 }

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語句前添加分頁代碼

1 ##application.properties
2 #指定數據庫方言
3 pagehelper.helperDialect=postgresql
4 #pageNum<=0時返回第一頁數據,pageNum超過總頁數時返回最後一頁數據
5 pagehelper.reasonable=true

相應代碼:

1 ##com.mobin.service.impl.SubwayServiceImpl
2 public List<Subway> findSubways(int pageNum,int pageSize){
3        //第三個參數爲fales時表示不對錶進行count操做
4        PageHelper.startPage(pageNum,pageSize,false);
5        return subwayMapper.findSubways();
6   }

 

項目地址:

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

參考資料:

GitHub API

How to use @RestControllerAdvice for handling Exception with RestfulApi

PageHelper使用方法

SerializerFeature使用詳解

logback相關配置

相關文章
相關標籤/搜索