# ybz **Repository Path**: wilson-zz/ybz ## Basic Information - **Project Name**: ybz - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-11-09 - **Last Updated**: 2025-02-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 人员:江振锋、张衍斌、舒展、杜帅、张金泉、姜磊、姜世杰、刘鹏、李彧业、于洪洲、何为、康凤伟、薛晓明、杜汉青、袁帅 资源: 接口文档:http://git.yonyou.com/sscplatform/fc_doc --所有人自己模块提供前段的接口都要记录在册 友报账后台:http://git.yonyou.com/jiangleid/ybz 工作台:http://git.yonyou.com/sscplatform/workbench nc报销:http://git.yonyou.com/ydbx/ermmobilenc jira:http://172.16.50.197:8080/secure/Dashboard.jspa wiki:http://172.16.50.96/pages/viewpage.action?pageId=78516010 nc补丁管理:http://git.yonyou.com/ybz-lab/NC-Patch-Warehouse 其他的知道的维护一下 前台分工 1.5、用户和密码(登录、找回密码、修改密码、租户切换,个人设置)、账本、智能推荐、第三方服务、结算中心、首页搜索、我的账表,动态表单(基础组件、工具类)--赵俊明 1.2、申请单(以及行程明细+费用明细)、nc审批、报销单-关联申请单、报销单-分组报销、报销单-审批历史、报销单-补助、动态表单组件(起始地、双日期、附件、电子发票、补助) -- 李景磊 1.3、借款还款单、扫一扫、我的单据、我的、原生插件、云审批、报销单-分摊、云影像和OCR —-吴雁江 1.4、打印、sass审批、我的发票列表 --刘建浩 1.5、扫码识别、小友机器人、本地插件、记事、报销单-明细列表、消息(客服,公告,通知,待办消息)、我的发票 --陈震华 =================== 1 后端模块分工 ======================== 架构:姜磊、姜世杰 功能点: 姜世杰:报销单、报销单冲借款、报销单拉申请、数据输出、web我的单据、客服消息、报销单附件 于洪洲:申请单、借款单、还款单、发票扫描二维码 杜帅:基本档案、工作台、档案翻译、参照过滤、电子发票 何为:报销单、企业费用分析、个人费用分析、会计中心 张金泉:商旅服务、移动审批、云审、公告、通知、我的待办 刘鹏:老记事、灵活记事、模板、档案翻译、报销标准、交叉校验规则、费用分析-预算分析、记事附件 李彧业:支付、结算中心、信用管理、申请控制规则、公式、参照过滤、小友机器人、首页全局搜索 袁帅:数据库升级、智能报销、智能推荐、企业注册、集成erp 江振锋:商旅服务、打印、第三方服务、单点登录 康凤伟:商旅服务、首页配置、费用分析-用车分析、代理报销 薛晓明:商旅服务、打印、第三方服务、单点登录 杜汉青:商旅服务、移动审批、云审、公告、通知、我的待办 姜磊:基础架构、mq、性能问题、服务器问题 张衍斌:用户、登录、运营平台 舒展:预算、app我的单据 nc专岗人员:姜世杰、张金泉、舒展 打包运行 all-in-one =================== 2 工程简介 ======================== 2.1 结构 工程是maven module结构,各module又分web、pri、pub三个project。 其中: web 主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等 pri 主要是自身业务应用的实现,包括 service、dao等 pub 主要是服务接口 常量 工具类,用于自己和其他工程调用。 如: ybz ----business-apply --------business-apply-web --------business-apply-pri --------business-apply-pub 2.2 pub模块依赖关系: 1)base可以依赖common; 2)business可以依赖common、base; 3)business-apply、business-loan、business-expense可以依赖business-note; 4)third-party可以依赖所有模块 2.3 非pub模块依赖 1)各模块间的依赖只能通过pub依赖,即依赖common-pub或各模块*-pub 2) 内部有依赖其他模块dao的,通过在其他模块pub中添加service接口解决依赖关系 3) 模块内部pri、web各只能依赖pub, 2.4 模块工程结构 project ----src/main/java (java代码) --------com.yonyou.ybz.模块.controller (controller内部禁止写业务逻辑,逻辑统一写在服务里service) --------com.yonyou.ybz.模块.service --------com.yonyou.ybz.模块.service.impl --------com.yonyou.ybz.模块.dao --------com.yonyou.ybz.模块.dao.mapping --------com.yonyou.ybz.模块.pojo ----src/main/resources (配置文件) --------develop(开发环境配置) --------test(测试环境配置) --------product(生产环境配置) ----src/test/java (测试用例) ----src/test/resources (测试配置文件) ----src/main/webapp (web工程的) 1)java文件放到 src/main/java, 配置文件放到src/main/resources(个性化配置放在对应目录develop、test、product) 2) 新建包 com.yonyou.ybz.模块名称.功能名称 如:com.yonyou.ybz.user.controller com.yonyou.ybz.user.service com.yonyou.ybz.user.mapper 2.5 代码生成 教程:http://baomidou.oschina.io/mybatis-plus-doc/#/ 工具:com.yonyou.framework.util.MybatisPlusGenerator 生成的目录结构与2.4相同 2.6 超类和注解(必须做) 1)必须做:新建类 接口以I开始,实现以Impl结尾,各层加上对应层级名。 如: UserController IUserService UserServiceImpl IUserDao/UserMapper 2)必须做:controller继承BaseController,service接口继承IBaseService, service实现继承BaseServiceImpl,mapper继承BaseMapper 3)spring组件注解,尽量使用明确含义的注解。如:controller用 @Controller、 service用@Service、 Dao 用@Repository,其他用@Component 4)资源注入,优先使用@Resource或是@Autowired @Qualifier。 强烈建议注入时指定beanName =================== 3 开发规范 ======================== 3.1 命名 1)类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:(领域模型的相关命名)DO/ BO / DTO/ VO等 2)方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式 3)常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长 4)抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类的名称开始,以Test结尾 5)POJO类中布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误 6)接口以I开头,实现类以Impl结尾,如:IUserService、 UserServiceImpl 7)枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开 8)Service/DAO层方法命名规约 a. 获取单个对象的方法用get做前缀 b. 获取多个对象的方法用list做前缀 c. 获取统计值的方法用count做前缀 d. 插入的方法用save(推荐)或insert做前缀 e. 删除的方法用remove(推荐)或delete做前缀 f. 修改的方法用update做前缀 9) 领域模型命名规约 a. 数据对象:xxxDO,xxx即为数据表名 b. 数据传输对象:xxxDTO,xxx为业务领域相关的名称 c. 展示对象:xxxVO,xxx一般为网页名称 d. POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO 3.2 常量定义 1)long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解 2)不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护 3) 常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量 a. 跨应用共享常量:放置在二方库中,通常是client.jar中的constant目录下 b. 应用内共享常量:放置在一方库的modules中的constant目录下 c. 子工程内部共享常量:即在当前子工程的constant目录下 d. 包内共享常量:即在当前包下单独的constant目录下 e. 类内共享常量:直接在类内部private static final定义 3.3 格式规约 1)大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果是非空代码块则: a. 左大括号前不换行。 b. 左大括号后换行。 c. 右大括号前换行。 d. 右大括号后还有else等代码则不换行;表示终止右大括号后必须换行 2)左括号和后一个字符之间不出现空格;同样,右括号和前一个字符之间也不出现空格 3)任何运算符左右必须加一个空格 4)缩进采用4个空格 5)单行字符数限制不超过120个,超出需要换行,换行时遵循如下原则: a. 第二行相对第一行缩进4个空格,从第三行开始,不再继续缩进. b. 运算符与下文一起换行。 c. 方法调用的点符号与下文一起换行。 d. 在多个参数超长,逗号后进行换行。 e. 在括号前不要换行. 正例: StringBuffer sb = new StringBuffer(); //超过120个字符的情况下,换行缩进4个空格,并且方法前的点符号一起换行 sb.append("zi").append("xin")... .append("huang")... .append("huang")... .append("huang"); 6)方法参数在定义和传入时,多个参数逗号后边必须加空格 7)IDE的text file encoding设置为UTF-8;IDE中文件的换行符使用Unix格式,不要使用windows格式 8)方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行 3.4 OOP规约 1)避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可 2)所有的覆写方法,必须加@Override注解 3)外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么 4)所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较 5)关于基本数据类型与包装数据类型的使用标准如下 a. 所有的POJO类属性必须使用包装数据类型 b. RPC方法的返回值和参数必须使用包装数据类型 c. 所有的局部变量使用基本数据类型 7)定义DO/DTO/VO等POJO类时,不要设定任何属性默认值 8)构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中 9)POJO类必须写toString方法。如果继承了另一个POJO类,注意在前面加一下super.toString 3.5 并发处理 1)获取单例对象需要保证线程安全,其中的方法也要保证线程安全 2)创建线程或线程池时请指定有意义的线程名称,方便出错时回溯 3)线程资源必须通过线程池提供,不允许在应用中自行显式创建线程 4)线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险 5)SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。 如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替Simpledateformatter 6)高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁 7)对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁 8)并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用version作为更新依据 9)多线程并行处理定时任务时使用ScheduledExecutorService 10)避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed导致的性能下降 在JDK7之后,可以直接使用APIThreadLocalRandom,在JDK7之前,可以做到每个线程一个实例 11)volatile解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。如果是count++操作,使用如下类实现: AtomicIntegercount = new AtomicInteger(); count.addAndGet(1); 如果是JDK8,推荐使用LongAdder对象,比AtomicLong性能更好(减少乐观锁的重试次数) 12)HashMap在容量不够进行resize时由于高并发可能出现死链,导致CPU飙升,在开发过程中注意规避此风险 13)ThreadLocal无法解决共享对象的更新问题,ThreadLocal对象建议使用static修饰。这个变量是针对一个线程内所有操作共有的,所以设置为静态变量, 所有此类实例共享此静态变量,也就是说在类第一次被使用时装载,只分配一块存储空间,所有此类的对象(只要是这个线程内定义的)都可以操控这个变量 3.6 注释规约 1)类、类属性、类方法的注释必须使用Javadoc规范,使用/**内容*/格式,不得使用//xxx方式 2)所有的抽象方法(包括接口中的方法)必须要用Javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能 3)所有的枚举类型字段必须要有注释,说明每个数据项的用途 4)特殊注释标记 待办事宜(TODO ) 错误,不能工作(FIXME) 3.7 异常 1)捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容 2)在代码中使用“抛异常”还是“返回错误码”,对于公司外的http/api开放接口必须使用“错误码”;而应用内部推荐异常抛出;跨应用间RPC调用优先考虑使用Result方式, 封装isSuccess、“错误码”、“错误简短信息 3.8 日志 1)应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一 2)异常信息应该包括两类信息:案发现场信息和异常堆栈信息 3.9 MySql 规约 0)字符集utf8,排序规则utf8_general_ci 1)表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsignedtinyint(1表示是,0表示否) 任何字段如果为非负数,必须是unsigned。 2)表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字 3)表名不使用复数名词 4)禁用保留字,如desc、range、match、delayed等 5)主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名 6)小数类型为decimal,禁止使用float和double,float和double在存储的时候,存在精度损失的问题。如果存储的数据范围超过decimal的范围,建议将数据拆成整数和小数分开存储 7)如果存储的字符串长度几乎相等,使用char定长字符串类型 8)varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率 9)表必备6个字段: id varchar(36) --程序生成主键IDUtil.get36UUID(), creator varchar(36) --创建人, create_time timestamp --创建时间, modified varchar(36) --修改人, dr char(1) --逻辑删除,0:未删除;1:删除, ts CURRENT_TIMESTAMP --勾选根据当前时间更新时间戳 9.1)字段必选添加注释 --方便数据字典抽取 10)表的命名最好是加上“业务名称_表的作用” 11)字段允许适当冗余,以提高性能,但是必须考虑数据同步的情况。冗余字段应遵循:不是频繁修改的字段,不是varchar超长字段,更不能是text字段 12)单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表 13)合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度 14)业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引 15)超过三个表禁止join。需要join的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引 16)搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。索引文件具有B-Tree的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引 17)建组合索引的时候,区分度最高的在最左边。但存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置 18)count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行 19)数据订正时,删除和修改记录时,要先select,避免出现误删除,确认无误才能执行更新语句 20)in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内 =================== 4 测试运行 ======================== 4.1 运行 all-in-one 4.2 日志路径 通过 log.properties配置 默认是 log.dir=/usr/local/logs/