項目地址:https://gitee.com/sanri/web-ui
優勢:這是一個 web 通用配置的組件,即插即用,可用於新項目或私活。是對 SpringBoot 快速開發的一種補充,它內置了大量的配置來簡化開發,遵循約定高於配置原則。前端
它解決的問題:java
發現BUG能夠提Issue,能夠給我發郵件,能夠加我QQ,能夠進9420技術羣討論.git
做者QQ: 2441719087web
做者郵箱: ningxiangsanri@163.comspring
9420 技術交流羣: 645576465mongodb
做者微信:sanri1993-json
我新開的一個項目,總結了多年的開發經驗所得,它具備的功能有後端
固定了輸入輸出格式前端框架
// 普通輸出格式 @Data public class ResponseDto<T> implements Serializable { // 0 字符串表示成功,不然失敗 private String code = "0"; private String message; private T data; } // 分頁輸出格式,是包裹在普通輸出格式中的,PageResponseDto 作爲 data 屬性 @Data public class PageResponseDto<T> { private List<T> rows; private Integer total; } // 分頁輸入格式 @Setter public class PageParam { private String pageNo; private String pageSize; }
對於 Controller 中的返回不用關心包裝類型,返回你所須要的類型就能夠了,對於 insert 單表操做能夠直接返回 void 微信
示例一:
@PostMapping("/insertUser") public void insertUser(User user){ xxxService.insert(user); }
它將會返回這樣的數據結構
{ "code":"0", "message":"ok", "data":null }
示例二:
@GetMapping("/queryUserById") public User queryUserById(Integer userId){ xxxService.queryUserById(userId); }
它將會返回這樣的數據結構
{ "code":"0", "message":"ok", "data":{ "userId":1, "username":"9420" } }
示例三:
對於分頁數據的處理
@GetMapping("/queryUserPage") public PageResponseDto<User> pageQuery(PageParam pageParam,Map<String,String> queryParams){ PageHelper.startPage(pageParam.getPageNo(),pageParam.getPageSize()); Page page = (Page) xxxService.pageQuery(queryParams); List result = page.getResult(); long total = page.getTotal(); return new PageResponseDto(result,total); }
它將會返回這樣的數據結構
{ "code":"0", "message":"ok", "data":{ "total":100, "rows":[{...},{...}] } }
示例四: 樹結構返回
對於樹型結構數據,你能夠用簡單數據返回,即原來的 List<Dto>
也能夠添加一個註解,使其成爲樹狀結構
//rootId 指定爲根結點 id @GetMapping("/treeShowMenu") @TreeResponse(type = MenuDto.class,rootId = "1") public List<Menu> treeShowMenu(){ List<Menu> menus = new ArrayList<>(); menus.add(new Menu(1,"全國",-1)); menus.add(new Menu(2,"湖南",1)); menus.add(new Menu(3,"長沙",2)); menus.add(new Menu(4,"深圳",1)); return menus; }
// 樹狀結構消息類 public class MenuDto extends RootTreeResponseDto<Menu> { public MenuDto(Menu origin) { super(origin); } @Override public String getId() {return origin.getId()+"";} @Override public String getParentId() {return origin.getPid()+"";} @Override public String getLabel() {return origin.getText();} @Override public Menu getOrigin() {return origin;} }
它將返回以下數據結構
{ "code": "0", "message": "ok", "data": [{ "origin": { "id": 1, "text": "全國", "pid": -1 }, "childrens": [{ "origin": { "id": 2, "text": "湖南", "pid": 1 }, "childrens": [{ "origin": { "id": 3, "text": "長沙", "pid": 2 }, "childrens": [], "id": "3", "label": "長沙", "parentId": "2" }], "id": "2", "label": "湖南", "parentId": "1" }, { "origin": { "id": 4, "text": "深圳", "pid": 1 }, "childrens": [], "id": "4", "label": "深圳", "parentId": "1" }], "id": "1", "label": "全國", "parentId": "-1" }] }
若是項目中出現業務操做不符合或調用第三方出錯,可以使用異常拋出,咱們將攔截成統一格式返回
示例一:
if(業務條件不知足){ throw BusinessException.create("業務提示信息"); }
它將會返回這樣的數據結構,code 是隨機生成的
{ "code":"234234", "message":"業務提示信息", "data":null }
示例二:
自定義 code 示例方法一
if(業務條件不知足){ throw BusinessException.create("E007","業務提示信息"); }
它將會返回這樣的數據結構
{ "code":"E007", "message":"業務提示信息", "data":null }
示例三:
自定義 code 示例方法二
// 配置異常代碼 public enum SystemMessage implements ExceptionCause<BusinessException> { SIGN_ERROR(4005,"簽名錯誤,你的簽名串爲 [%s]"),; ResponseDto responseDto = new ResponseDto(); private SystemMessage(int returnCode,String message){ responseDto.setCode(returnCode+""); responseDto.setMessage(message); } public BusinessException exception(Object...args) { return BusinessException.create(this,args); } }
使用異常
if(業務條件不知足){ throw SystemMessage.SIGN_ERROR.exception("簽名串"); }
它將會返回這樣的數據結構
{ "code":"4005", "message":"簽名錯誤,你的簽名串爲 [簽名串]", "data":null }
你覺得它就這麼點能耐嗎,它還自帶參數空格過濾功能,還能夠定義特殊字符和諧
你只須要注入一個處理器,它就能工做,注入方式以下
@Bean("paramHandler") public Function paramHandler(){ return param -> param.replace("<","《"); }
自帶了日期轉化(輸入)功能,能夠支持的日期格式有
final String[] parsePatterns = new String[]{"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.S"};
如今是固定這三種格式 ,後面會放開讓使用者本身配置
支持校驗器,已經幫你設置好了兩個 group ,直接使用便可
public interface Insert { } public interface Update { }
支持大文件上傳,文件秒傳,文件驗證;你只須要配置幾個選項便可使用
# 文件上傳的位置 sanri.webui.upload.basePath=d:/test/ # 臨時文件路徑 spring.servlet.multipart.location=d:/tmp
或者你想上傳到別的地方,那就須要本身實現 com.sanri.web.bigfile.BigFileStorage
而後注入 IOC 到容器
@Bean public BigFileStorage bigFileStorage(){ return new LocalBigFileStorage(); }
已經幫你添加了一個 controller ,用於大文件上傳,下面是接口說明
GET /upload/file/fileMetaData?originFileName=原始文件名&fileSize=文件大小&md5=文件 md5
返回 FileMetaData
數據,重要的數據是那個相對路徑 relativePath
由於它是接下來全部接口的入參
GET /upload/file/filePosition?relativePath=相對路徑
返回 文件當前上傳的大小,用於斷點續傳
POST /upload/file/uploadPart?relativePath=相對路徑
body 中添加 form-data 參數,file=文件
返回上傳文件位置
GET /upload/file/validateFile?relativePath=相對路徑&fileSize=文件大小&md5=文件 md5 值
返回文件是否正常上傳,無損壞
引入包或下載 jar 包文件
<dependency> <groupId>com.sanri.web</groupId> <artifactId>web-ui</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
開啓快速開發
@EnableWebUI
若是想開啓大文件上傳
@EnableBigFileUpload
能夠爲方法標記記錄日誌功能,這是很常見的一個功能,感謝網友 東莞-隊長(qq: 1178130627) 的朋友提出
由於日誌每一個系統有各自的作法,有的可能還須要把日誌存儲到 mongodb
中去,因此不可能所有統一塊兒來,註解也是不支持繼承的;因此個人解決辦法是,我能夠幫你儘量的解析出一些參數來,但具體的實現邏輯還須要你本身來弄,框架默認會給你注入一個把日誌打印到控制檯的功能。
使用方法爲使用註解標記當前方法,它將默認使用 com.sanri.web.logmark.Slf4jLogInfoHandler
來記錄日誌
@GetMapping("/testParamTrim") @SysLogMark public void testParamTrim(TestParam testParam){}
兼容性說明 :
application/x-www-form-urlencoded
類型參數application/form-data
類型參數application/json
類型參數固然,我會排除文件類型的參數,它太龐大了,不可能打印在日誌裏面
實現本身的日誌記錄方法:注入一個 LogInfoHandler
的 Bean 到 IOC 容器中
新增配置
# 日誌參數打印,可支持的項有 base,param,header,body sanri.webui.logmark.showInfos=base,param,header,body
一些經常使用校驗器和通用預覽和下載功能,比較經常使用,這裏給所有集成了
參數校驗器使用方法
// 必須爲強密碼 @NotNull @Password(strength = Password.Strength.STRONG) private String password;
其它經常使用驗證器
@UserName
驗證參數是否爲用戶名@Password
驗證參數是否爲密碼@IdCard18
驗證參數是否爲 18 位身份證能夠在 resources 目錄下放置一個區域代碼,作更強的驗證,文件名爲 areaCodes
,文件內容以逗號分隔全部的區域代碼
@EnumIntValue
和 @EnumStringValue
驗證參數是否爲枚舉值增長一些文件下載,預覽方法,和 request 請求信息的獲取
@Autowired RequestInfoHelper requestInfoHelper; @Autowired StreamHelper streamHelper;
修改處理器注入方式 ,使用本身的接口 ParamHandler
,不使用 Function
@Bean("paramHandler") public ParamHandler paramHandler(){ return param -> param.replace("<","《"); }
爲解決前端 mm 須要後端人員返回樹形結構數據問題,其實大部分框架已經支持簡單樹形數據,像 ztree ,但也有的前端框架是須要後端幫忙轉化一下數據結構的,因此特加此功能
這個樹形結構的轉換使用了一個快速轉換的機制,充分利用了對象在內存中地址的原理,實測在萬條數據轉換爲 10ms 左右,使用方法是先實現一個 TreeResponseDto
的類,而後在 Controller 中添加一個註解
@TreeResponse(type = MenuDto.class,rootId = "1")