项目地址: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")