主机: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
JDK1.8 下载 eclipse 下载 IDEA 下载 navicat mac下载 gradle 下载 git 下载 sourceTree mac下载 postman 下载
阿里开发规范 下载
注意: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支持参数校验:
@RequestMapping(path="/test/v1", method=RequestMethod.POST)
@ResponseBody
public MJson<Void> 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代码层处理。
<mvc:annotation-driven validator="validator"/>
<bean id="validator" class="com.sp.core.valid.NoOpValidator" />
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="paramtersValidInterceptor" class="com.sp.core.valid.ParamtersValidInterceptor"/>
<aop:config>
<aop:pointcut id="controller" expression="execution(* com.sp.bore.module.*.*Controller.*(..))"/>
<aop:advisor advice-ref="paramtersValidInterceptor" pointcut-ref="controller" />
</aop:config>
@RequestMapping(path="/test/v1", method=RequestMethod.POST)
@ResponseBody
public MJson<Void> 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框架可减少网络传输 需要考虑错综复杂的服务调用关系
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
<bean id="cacheManager" class="org.springframework.cache.concurrent.ConcurrentMapCacheManager" />
@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生成参数
客户端: