分享一個基於Spring Boot的API、RESTful API項目種子(骨架)!


  • 前言
  • 特徵&提供
  • 技術選型&文檔

前言

最近使用Spring Boot 配合 MyBatis 、通用Mapper插件、PageHelper分頁插件 連做了幾個中小型API項目,做下來覺得這套框架、工具搭配起來開發這種項目確實非常舒服,團隊的反響也不錯。在項目搭建和開發的過程中也總結了一些小經驗,與大家分享一下。

在開發一個API項目之前,搭建項目、引入依賴、配置框架這些基礎活自然不用多說,通常為了加快項目的開發進度(早點回家)還需要封裝一些常用的類和工具,比如統一的響應結果封裝、統一的異常處理、接口簽名認證、基礎的增刪改差方法封裝、基礎代碼生成工具等等,有了這些項目才能開工。

然而,下次再做類似的項目上述那些步驟可能還要搞一遍,雖然通常是拿過來改改,但是還是比較浪費時間。所以,可以利用面向對象抽象、封裝的思想,抽取這類項目的共同之處封裝成了一個種子項目(估計大部分公司都會有很多類似的種子項目),這樣的話下次再開發類似的項目直接在該種子項目上迭代就可以了,減少無意義的重複工作。

在相關項目上線之後,我花了點時間對該種子項目做了一些精簡,並且已經把該項目分享到GitHub上面了,如果你正準備做類似項目的話,可以去克隆下來試試。

如果在使用中發現問題或者有什麼好建議的話歡迎提issue或pr一起來完善它。

特徵&提供

最佳實踐的項目結構、配置文件、精簡的POM

分享一個基於Spring Boot的API、RESTful API項目種子(骨架)!

注:使用代碼生成器生成代碼後會創建model、dao、service、web等包。

統一響應結果封裝及生成工具

<code> 

public

class

Result

{

private

int code;

private

String message;

private

Object

data

;

public

Result setCode(ResultCode resultCode) {

this

.code = resultCode.code;

return

this

; } }/<code>
<code> 

public

enum

ResultCode { SUCCESS(

200

), FAIL(

400

), UNAUTHORIZED(

401

), NOT_FOUND(

404

), INTERNAL_SERVER_ERROR(

500

);

public

int

code; ResultCode(

int

code) {

this

.code = code; } }/<code>
<code> 

public

class

ResultGenerator

{

private

static

final

String DEFAULT_SUCCESS_MESSAGE =

"SUCCESS"

;

public

static

Result

genSuccessResult

()

{

return

new

Result() .setCode(ResultCode.SUCCESS) .setMessage(DEFAULT_SUCCESS_MESSAGE); }

public

static

Result

genSuccessResult

(Object data)

{

return

new

Result() .setCode(ResultCode.SUCCESS) .setMessage(DEFAULT_SUCCESS_MESSAGE) .setData(data); }

public

static

Result

genFailResult

(String message)

{

return

new

Result() .setCode(ResultCode.FAIL) .setMessage(message); } }/<code>

統一異常處理

<code>  

public

void

configureHandlerExceptionResolvers(List exceptionResolvers) { exceptionResolvers.add(

new

HandlerExceptionResolver() {

public

ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,

Object

handler, Exception e) { Result result =

new

Result();

if

(e

instanceof

ServiceException) { result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); logger.info(e.getMessage()); }

else

if

(e

instanceof

NoHandlerFoundException) { result.setCode(ResultCode.NOT_FOUND).setMessage(

"接口 ["

+ request.getRequestURI() +

"] 不存在"

); }

else

if

(e

instanceof

ServletException) { result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); }

else

{ result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage(

"接口 ["

+ request.getRequestURI() +

"] 內部錯誤,請聯繫管理員"

);

String

message;

if

(handler

instanceof

HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; message =

String

.format(

"接口 [%s] 出現異常,方法:%s.%s,異常摘要:%s"

, request.getRequestURI(), handlerMethod.getBean().getClass().getName(), handlerMethod.getMethod().getName(), e.getMessage()); }

else

{ message = e.getMessage(); } logger.error(message, e); } responseResult(response, result);

return

new

ModelAndView(); } }); }/<code>

常用基礎方法抽象封裝

<code>

public

interface

Service

<

T

>

{

void

save

(T model)

;

void

save

(List models)

;

void

deleteById

(Integer id)

;

void

deleteByIds

(String ids)

;

void

update

(T model)

;

T

findById

(Integer id)

;

T

findBy

(String fieldName, Object value)

throws

TooManyResultsException

;

List

findByIds

(String ids)

;

List

findByCondition

(Condition condition)

;

List

findAll

()

; }/<code>

提供代碼生成器來生成基礎代碼

<code>

public

abstract

class

CodeGenerator

{ ...

public

static

void

main

(

String[] args

)

{ genCode(

"輸入表名"

); }

public

static

void

genCode

(

String... tableNames

)

{

for

(String tableName : tableNames) { genModelAndMapper(tableName); genService(tableName); genController(tableName); } } ... }/<code>

CodeGenerator 可根據表名生成對應的Model、Mapper、MapperXML、Service、ServiceImpl、Controller(默認提供POST和RESTful兩套Controller模板,根據需要在 genController(tableName)方法中自己選擇,默認是純POST的),代碼模板可根據實際項目的需求來定製,以便漸少重複勞動。

由於每個公司業務都不太一樣,所以只提供了一些簡單的通用方法模板,主要是提供一個思路來減少重複代碼的編寫。在我們公司的實際使用中,其實根據業務的抽象編寫了大量的代碼模板。

提供簡單的接口簽名認證

<code>

public

void

addInterceptors

(InterceptorRegistry registry)

{

if

(!

"dev"

.equals(env)) { registry.addInterceptor(

new

HandlerInterceptorAdapter() {

public

boolean

preHandle

(HttpServletRequest request, HttpServletResponse response, Object handler)

throws

Exception

{

boolean

pass = validateSign(request);

if

(pass) {

return

true

; }

else

{ logger.warn(

"簽名認證失敗,請求接口:{},請求IP:{},請求參數:{}"

, request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap())); Result result =

new

Result(); result.setCode(ResultCode.UNAUTHORIZED).setMessage(

"簽名認證失敗"

); responseResult(response, result);

return

false

; } } }); } }/<code>
<code> 

private

boolean

validateSign(HttpServletRequest request) {

String

requestSign = request.getParameter(

"sign"

);

if

(StringUtils.isEmpty(requestSign)) {

return

false

; } List<

String

> keys =

new

ArrayList<

String

>(request.getParameterMap().keySet()); keys.remove(

"sign"

); Collections.sort(keys); StringBuilder sb =

new

StringBuilder();

for

(

String

key : keys) { sb.append(key).append(

"="

).append(request.getParameter(key)).append(

"&"

); }

String

linkString = sb.toString(); linkString = StringUtils.substring(linkString,

0

, linkString.length() -

1

);

String

secret =

"Potato"

;

String

sign = DigestUtils.md5Hex(linkString + secret);

return

StringUtils.equals(sign, requestSign); }/<code>

集成MyBatis、通用Mapper插件、PageHelper分頁插件,實現單表業務零SQL

使用Druid Spring Boot Starter 集成Druid數據庫連接池與監控

使用
FastJsonHttpMessageConverter,提高JSON序列化速度

技術選型&文檔

Spring Boot:https://www.jianshu.com/p/1a9fd8936bd8

MyBatis:http://www.mybatis.org/mybatis-3/zh/index.html

MyBatisb通用Mapper插件:
https://mapperhelper.github.io/docs/

MyBatis PageHelper分頁插件:
https://pagehelper.github.io/

Druid Spring Boot Starter:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter/

Fastjson:https://github.com/Alibaba/fastjson/wiki/%E9%A6%96%E9%A1%B5

後言

感謝大家的支持,沒想到一個簡單的項目總結分享在短短兩天獲得這麼多人的關注,還上了GitHub Trending榜單,有點受寵若驚哈,話說現在國內技術社區氛圍真是越來越好了,希望大家有時間的話都能參與到開源分享的行列來,分享知識,快樂編碼,共勉。

分享一個基於Spring Boot的API、RESTful API項目種子(骨架)!


分享到:


相關文章: