java入职学习一之编码规范

编码规范

  1. 好的编码规范可以尽可能的减少一个软件的维护成本,并且几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护。
  2. 好的编码规范可以改善软件的可读性,可以让开发人员尽快而彻底地理解新的代码。
  3. 好的编码规范可以最大限度的提高团队开发的合作效率。
  4. 长期的规范性编码还可以让开发人员养成好的编码习惯,甚至锻炼出更加严谨的思维。

一、安全规约

通过学习阿里巴巴的《阿里巴巴Java开发手册》和公司视频讲解,发现这七大强制约定和一个推荐约定的对于一个开发人员的良好编码习惯和逻辑思维有着重要的启发和引导作用。

1.1隶属于用户个人的页面或者功能必须进行权限控制校验。

说明:防止没再做水平权限校验就可随意访问 、修改、删除别
人的数据,比如查看他人的私信内窑、修改他人的订单

1.2用户敏感数据禁止直接展示,必须对展示数据进行脱敏。

说明:查看个人手机号码会显示成:178****3012 ,隐藏中间4位,防止隐私泄露。
数据脱敏:对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。

1.3用户输入的SQL参数严格使用参数绑定或者METADATA字段值限定,防止sql注入,禁止字符串拼接sql访问数据库。

METADATA:元数据,又称中介数据、中继数据,为描述数据的数据,主要描述数据属性的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能
#{}是通过占位?的形式对sql语句进行先编译后引用,可以有效的防止sql注入攻击
${}不经过预编译,直接通过字符串拼接是的形式。容易造成sql注入攻击

1.4用户请求传入的任何参数必须做有效性验证。

忽略参数校验可能导致:
1)page size过大导致内存溢出;
2)恶意order by导致数据库慢查询
3)任意重定向
4)SQL注入
5)反序列化注入
6)正则输入源串拒绝服务ReDoS【正则表达式拒绝服务攻击和防御】
说明:Java代码用正则来验证客户端的输入,有些正则写法验证普通用户输入没有问题,但是如果攻击人员使用的是特殊构造的字符串来验证,有可能导致死循环的结果。

1.5禁止向HTML页面输出未经安全过滤或未正确转义的用户数据。

出口:一般指的是web页面,系统的出口要堵住特殊字符,
入口:可能是web页面也可能是开发接口,保证系统入口也不要有特殊字符,
可以在不同版本和设备上的自由使用,而不会造成编码错误

1.6表单、AJAX提交必须执行CSRF安全过滤。

说明:CSRF(Cross-site request forgery)跨站请求伪造是一类常见编程漏洞。对于存在CSRF漏洞的应用/网站,攻击者可以事先构造好URL,只要受害者用户一访问,后台便在用户不知情情况下对数据库中用户参数进行相应修改。
攻击者不是获取用户的账户信息和控制权,而是通过欺骗用户浏览器,以用户的名义进行操作,
验证方法:
1)检查Referer字段
Refere:Header中的信息,代表访问来源站点的地址
优点:简单易行,工作量低,仅需要在关键访问增加一步校验
缺点:有局限性,完全依赖于浏览器,可能被恶意浏览器篡改referer内容
2)添加校验token
方式:服务器给在客户端发送请求时,生产一个随机数,并保存到redis或者服务器中,并发送到客户端。用户提交表单时,服务器会获取这个随机数并和服务器存储的数据进行比较验证
优点:更加安全,可以有效防止csrf
缺点:有一定的工作量

1.7在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放限制,如数量限制、疲劳度控制、验证码校验,避免被滥刷、资损。

说明:如注册时发送验证码到手机,如果没有限制次数和频率,那么可以利用此功能骚扰到其他用户,并造成短信平台资源浪费。
作用1.减少资源的浪费2.防止刷新页面导致订单或者支付重复,

1.8发帖、评论、发送即时消息等用户生成内容的场景必须实现防刷、文本内容违禁词过滤等风控策略。

二、mysql数据库

底层数据库的规范有助于减少软件实现的复杂度,降低沟通成本,本
章主要说明建表规范 索引优化准则以及 ORM 层的处理约定。

(一)建表规范

1.1表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint( 1表示是,0表示否)。

说明:任何字段如果为非负数,必须是unsigned。
正例:表达逻辑删除的字段名is_deleted,1表示删除,0表示未删除。

1.2表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。

说明: MySQL Wind 下不区分大小写,但在 inux 下默
认区分大小写 因此,数据库名 表名 字段名都不允
许出现任何大写字母 避免节外生枝
正例:getter_admin,task_config,level3_name
反例:GetterAdmin,taskConfig,level_3_name

1.3表名不使用复数名词。

说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于DO类名也是单数形式,符合表达习惯。

1.4禁用保留字,如desc、range、match、delayed等,请参考MySQL官方保留字。
1.5主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。

说明:pk_ 即primary key;uk_ 即 unique key;idx_ 即index的简称。

1.6小数类型为decimal,禁止使用float和double。

说明:float和double在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。如果存储的数据范围超过decimal的范围,建议将数据拆成整数和小数分开存储。

1.7如果存储的字符串长度几乎相等,使用char定长字符串类型。
1.8 varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,

如果存储长度大于5000,定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。

1.9表必备三字段:id, gmt_create/creat_time, gmt_modified/update_time。

说明:其中id必为主键,类型为unsigned bigint、单表时自增、步长为1。gmt_create/creat_time, gmt_modified/update_time的类型均为date_time类型。gmt_create/creat_time,建表时间,gmt_modified/update_time,修改时间。

1.10.表的命名最好是加上“业务名称_表的作用”。

正例:tiger_task / tiger_reader / mpp_config

1.11库名与应用名称尽量一致。

(二)索引规约

2.1业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯 索引。

说明:不要以为唯一索引影响了 insert 速度,这个速度损耗
可以忽略,但会明显提高查找速度;另外,即使在应用
层做了非常完善的校验控制,只要没再唯一索引 ,根据
墨菲定律,必然高脏数据产生。

2.2超过 个表禁止 join 需要 jo 川的字段,数据必须绝对 致;当多表关联查询时,保证被关联的宇段需要有索引。

说明·即使双表 join 也要注意表索引、 SQL 性能。

2.3 varchar 字段上建立索引时,必须指定索引长度,没必要对全宇段建立索引,根据实际文本区分度决定索引长度即可。

说明·索引的长度与区分度是一对矛盾体,一般对字符串类型
数据,七三度为 20 的索引,区分度会高达 90 毡以上,可以
使用 count (distinct left (列名,索引
度))/ count (门的区分度来确定

2.4页面搜索严禁左模糊或者全模糊,如果需要请通过搜索引擎来解决

说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边
的值未确定,那么无法使用此索引。

2.5创建索引时避免有如下极端误解

1)宁滥勿缺。认为一个查询就需要建一个索引
2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增
速度
3)抵制唯一索引。认为业务的唯一性,一律需要在应用层通过“先查后插”的方式解决

2.6建组合索引的时候,区分度最高的在最左边。

正例:如果where a=? and b=? ,a列的几乎接近于唯一值,那么只需要单建idx_a索引即可。
说明:存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。
如:where a>? and b=? 那么即使a的区分度更高,也必须把b放在索引的最前列。

2.7如果有order by的场景,请注意利用索引的有序性。

order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort的情况,影响查询性能。
正例:where a=? and b=? order by c; 索引:a_b_c
反例:索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引a_b无法排序。

(三)SQL语句

3.1【强制】不要使用count(列名)或count(常量)来替代count(*), count(*)是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。

说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。

3.2 【强制】count(distinct col) 计算该列除NULL之外的不重复行数,

注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。

3.3【强制】当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。

正例:可以使用如下方式来避免sum的NPE问题:SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;

3.4 【强制】使用ISNULL()来判断是否为NULL值。注意:NULL与任何值的直接比较都为NULL

说明: 1) NULL<>NULL的返回结果是NULL,而不是false。
2) NULL=NULL的返回结果是NULL,而不是true。
3) NULL<>1的返回结果是NULL,而不是true。

3.5 【强制】 在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。
3.6 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。

说明:(概念解释)学生表中的student_id是主键,那么成绩表中的student_id则为外键。
如果更新学生表中的student_id,同时触发成绩表中的student_id更新,则为级联更新。
外键与级联更新适用于单机低并发,不适合分布式、高并发集群;
级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

3.7 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
3.8 【强制】数据订正时,删除和修改记录时,要先select,避免出现误删除,确认无误才能执行更新语句。
3.9 【推荐】in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。
3.10【参考】如果有全球化需要,所有的字符存储与表示,均以utf-8编码,注意字符统计函数的区别。

说明: SELECT LENGTH(“轻松工作”); 返回为12;
SELECT CHARACTER_LENGTH(“轻松工作”); 返回为4
如果要使用表情,那么使用utfmb4来进行存储,注意它与utf-8编码的区别

3.11【参考】 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但TRUNCATE无事务且不触发trigger,有可能造成事故,故不建议在开发代码中使用此语句。

说明:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。

(四)ORM映射

4.1【强制】在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。

说明:1)增加查询分析器解析成本。
2)增减字段容易与resultMap配置不一致。

4.2【强制】POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行字段与属性之间的映射。

说明:参见定义POJO类以及数据库字段定义规定,在中增加映射,是必须的。
在MyBatis Generator生成的代码中,需要进行对应的修改。

4.3 【强制】不要用resultClass当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义;

反过来,每一个表也必然有一个与之对应。 说明:配置映射关系,使字段与DO类解耦,方便维护。一般不用,resulttype和resultmap就够操作了

4.4 【强制】sql.xml配置参数使用:#{},#param# 不要使用${} 此种方式容易出现SQL注入。
4.5 【强制】iBATIS自带的queryForList(String statementName,int start,int size)不推荐使用。

说明:其实现方式是在数据库取到statementName对应的SQL语句的所有记录,再通过subList取start,size的子集合。分页,一般都用limit
正例:Map<String, Object> map = new HashMap<String, Object>();
map.put(“start”, start);
map.put(“size”, size);

4.6 【强制】不允许直接拿HashMap与Hashtable作为查询结果集的输出。

说明:resultClass=”Hashtable”,会置入字段名和属性值,但是值的类型不可控。

4.7 【强制】更新数据表记录时,必须同时更新记录对应的gmt_modified/update_time字段值为当前时间。

spring boot代码编写注意事项

一、ResTful API 风格

1.1 Restful简介

springMVC对编写Restful Api提供了很好的支持。
Restful Api有三个主要的特性:
1.是基于Http协议的,是无状态的。
2.是以资源为导向的
3.人性化的,返回体内部包含相关必要的指导和链接
面向资源?
传统的Api接口以动作为导向,并且请求方法单一。
例如 /user/query?id=1 GET方法 ;
/user/create POST方法
而在resultful风格下以资源为导向,
例如: /user/id(GET方法,获取) /user/(POST方法,创建)
restful api 用url描述资源,用Http方法描述行为,用Http状态码描述不同的结果,使用json作为交互数据(包括入参和响应)
restful只是一种风格并不是一种强制的标准
@PathVariable

/**
 * 映射url片段到java方法参数
 */
@GetMapping("/user/{id}")
    public User getUserInfo(@PathVariable("id") String id){
        return new User("sico","12345");
    }
    
   /**
     * 获取用户详情,利用正则表达式限定为只接收数字
     * @param id
     * @return
     */
    @GetMapping("/user/{id:\\d+}")
    public User getUserInfo(@PathVariable("id") String id){
        return new User("sico","12345");
    }

RequestMapping的变体
RequestMapping有以下变体,他们分别对应了不同的请求方法
@GetMapping 对应GET方法
@PostMapping 对应POST方法
@PutMapping 对应PUT方法
@DeleteMapping 对应DELETE方法
@RequestBody将请求体映射到java方法参数
@(spring)RequestBody将请求中的请求体中的实体数据转换

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值