## 测试环境 主机:120.79.211.173 用户名:spu 密码:Shanpin#!#20180201 SFTP:120.79.211.173 用户名:spu 密码:Shanpin#!#20180201 git私库: http://120.79.211.173:3000 项目部署路径: /srv/server/ nginx配置路径: /etc/nginx/ mysql配置路径: /etc/my.cnf **TODO** 1. 主机每个用户单独一个帐号,权限区分开 1. 数据库每个项目对应一个帐号,帐号仅有本数据库的增删改查权限,没有其它库权限,且没有DROP,CREATE等权限 ## 开发工具 JDK1.8 [下载](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html "下载") eclipse [下载](https://www.eclipse.org/downloads/ "下载") IDEA [下载](http://www.jetbrains.com/idea/download/ "下载") navicat [mac下载](http://120.79.211.173/tool/mac/navicat/navicat_for_mysql_for_mac.zip "mac下载") gradle [下载](https://gradle.org/releases/ "下载") git [下载](https://git-scm.com/downloads "下载") sourceTree [mac下载](http://120.79.211.173/tool/mac/sourceTree/SourceTree_2.2.4.dmg.zip "mac下载") postman [下载](https://www.getpostman.com/downloads/ "下载") ## 开发规范 阿里开发规范 [下载](http://120.79.211.173/book/阿里巴巴Java开发规范手册.pdf "下载") #### 命名规范 注意:boolean变量不能is开头命名(RPC框架序列化可能会出错) Param 参数对象,封装查询,更新,新加等参数。对于数量超过三个,则需要封装。除非确定参数数量不会改变 VO 值对象,Controller返回,用于客户端展示,服务端Controller负责参数合法性校验和对Service数据转义处理 DTO 数据传输对象,Service返回,用于业务属性封装 PO 持久化对象,和数据库表对应 Abstract 抽象类 Controller 控制层 Service 服务层 DAO 数据库访问层 #### 工具类规范 公司工具类>apache common util/google util>spring util 工具类:com.sp.core.util 提供字符串,加密,日期等工具类 #### 异常规范 异常是耗时操作 捕获的异常,不允许什么都不处理,最少都要打印日志,打印日志禁止用e.printStacktrace(),System.out。统一使用 服务层处理过程出现不可预见异常统一抛出ServiceException 异常统一封装处理 #### 日志规范 业务日志: 方案选择: lockback日志,日志保留30天。 目录:work/log/ 日志类型:是否需要区分日志类型? 比如支付日志,请求参数日志。 日志级别: 测试环境:info 生成环境:warn debug 调试信息 info warn 重要日志,异常但是已考虑了容错。 error 异常日志,不可预见,会发出通知日志给负责人。 自定义LOG注解: 超级重要日志(支付报文),持久化存储。 注意:正常业务请求不应该出现error日志,出现error日志就是要去处理的。 日志链路追踪: 客户端生成追踪的requestId,服务端透传,日志打印,自动获取requestId。 nginx日志: nginx日志格式统一 #### 事务规范 为了数据一致性,统一启用事务 数据库隔离级别:可重复读 方案选择: 统一在Service层加事务。 通过AOP?注解? ### 参数校验规范 禁用spring @Validated,使用javax @Valid。 说明:spring校验支持@Valid。 hibernate valid校验框架 优点: 1、控制层或业务层不存在太多和校验相关代码,校验逻辑封装实体内,功能内聚。 校验出错异常逻辑统一处理。 2、实现java规范 存在问题: 1、Spring Validate在WebInitDataBinder做参数校验,不支持整个方法参数校验。不支持对基础类型校验,只能对javaBean默认是@ModelAttribute转过程中处理。 例如SpringMVC校验对passwd简单类型不支持,对userParam支持参数校验: ```java @RequestMapping(path="/test/v1", method=RequestMethod.POST) @ResponseBody public MJson test( @ApiIgnore @CurrentUser UserLoginInfo loginInfo, @NotBlank(message="密码为空") String passwd, @Valid UserParam userParam) { userService.updatePasswd(loginInfo.getUserId(), passwd); return MJson.ok(); } ``` 2、对@valid注解,不支持分组校验。 方案选择: 简单封装hibernate valid,具体代码:com.sp.core.valid下: 禁用掉Spring Validate逻辑,目前Spring没有直接禁用,替换掉校验类,用AOP自己做方法参数校验,暂时不支持分组校验。 1、官方提供的校验注解比较少,自定义注解放在com.sp.core.valid.validator(如果和业务关联的自定义注解,放到业务代码那边,不要放在这个sp-core下) 2、如果需要分组校验场景,建议暂时放到java代码层处理。 3、对于复杂场景的校验,例如检查是否数据库存在,或者数据之间关联关系建议放到java代码层处理。 ```xml ``` ```java @RequestMapping(path="/test/v1", method=RequestMethod.POST) @ResponseBody public MJson test( @ApiIgnore @CurrentUser UserLoginInfo loginInfo, @NotBlank(message="密码为空") String passwd, @Valid UserParam userParam) { userService.updatePasswd(loginInfo.getUserId(), passwd); return MJson.ok(); } ``` 方案问题: 如果要支持分组校验,需要注解侵入,且支持分组力度只能是方法 方案替换成本: 暂无 ### 缓存框架 1、不建议更新DB同步更新缓存,除非内容只增不改。 2、先失效缓存再更新DB,容易造成缓存了旧数据,故也不建议。 3、可先更新DB,再失效缓存。 spring-cache 优点: 1、具体缓存可动态切换 2、springEL高度灵活 存在问题: 1、spring-cache不支持TTL 2、不支持多级缓存 3、失去数据一致性 (数据库隔离级别有问题,数据库回滚策略有问题) 目前方案: 使用spring-cache注解,使用ConcurrentHashMap,暂时不考虑事务影响 DAO层? 缓存数据清晰点 事务隔离级别(破坏数据一致性) Service层? 对RPC框架可减少网络传输 需要考虑错综复杂的服务调用关系 ```xml ``` ```java @Cacheable(value="address", key="#addressId") public AddressPO get(int addressId) { return super.get(addressId); } ``` 方案替换成本: 更换DAO层cache注解 未来: 1、cache动态生效(JMX,http) 2、cache命中率,大小等监控(精确到某种类型) ## 数据库规范 数据库编码 utf8mb4-兼容utf8且支持 数据库表和字段必须加注释 数据库字段类型和长度选择,比入ip,phone,nick_name(这种)等 选择考虑存储,效率 数据库枚举类字段不建议使用enum,建议使用tinyint 数据库建议单表查询,数据库不要承接太多业务查询逻辑 ## 工程规范 core包,存放和业务无关的代码,比如工具类,对工具使用二次封装 sp-core 插件工程(manager), 封装第三方依赖,比如短信,支付,微信公众号,微信小程序通用功能 sp-plugin-sms 短信 sp-plugin-push 推送 sp-plugin-pay 支付 中心服务,提供完整服务,比如订单服务(支付,退款,对帐),短信(短信风控) 具体项目,具体业务代码 bore-core 具体业务核心包 bore-admin 具体业务后台 bore-web 具体业务网页(pc/wap/活动页面等) bore-api/logic (移动端项目) bore-task(定时任务) 待处理: 静态参数管理(目标提供一致规范的静态参数管理) 服务端:对于不可变或新加需要修改代码逻辑的采用枚举类(用户状态) 对于可变,可动态加采用配置表,比如银行配置 支持动态sql,通过sql生成参数 客户端: