首页 Java开发规范(公司规范)

Java开发规范(公司规范)

举报
开通vip

Java开发规范(公司规范)Java开发规范(公司规范) 第1章 序言 本规范的目的在于:建立一个可行可操作的编程标准、约定和指南,以规范公司java代码研发工作。 2013年为公司的质量年,为了提高公司研发能力,该规范的制定是为了规范java代码开发,提高java开发质量,从代码的层面规范并提高java项目的研发水平。该规范由运营中心技术小组制定,运营中心技术小组将结合PMD检查工具以及相应的检查工具,组织技术监控人员对重点项目以及新的java项目定期检查,对代码质量进行评估,对代码质量较差限期整改,并报运营中心备案作为项目考核依据。...

Java开发规范(公司规范)
Java开发规范(公司规范) 第1章 序言 本规范的目的在于:建立一个可行可操作的编程标准、约定和指南,以规范公司java代码研发工作。 2013年为公司的质量年,为了提高公司研发能力,该规范的制定是为了规范java代码开发,提高java开发质量,从代码的层面规范并提高java项目的研发水平。该规范由运营中心技术小组制定,运营中心技术小组将结合PMD检查工具以及相应的检查工具,组织技术监控人员对重点项目以及新的java项目定期检查,对代码质量进行评估,对代码质量较差限期整改,并报运营中心备案作为项目考核依据。 本规范适用于2013年公司java代码研发规范。本规范的内容包括两个方面:java开发一般规范,以及java代码开发安全性规范。Java代码开发一般规范主要从java基本语法,代码格式,耦合性以及 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 方面,以及代码质量因子等进行描述;java代码开发安全性规范主要从sql注入,资源注入,跨站脚步,安全边界违例,系统信息泄露进行描述。 为了方便并配合PMD检查工具等相应检查工具,方便开发者针对违规代码进行调整,本规范中java一般开发规范描述形式将结合PMD,并提供示例代码,其形式如下: , 规范描述: , PMD规则名称: , PMD级别(注1): , 违规示例代码: , 合法示例代码: 本规范中java安全开发规范部分将结合具体项目,对出现安全隐患的代码进行 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 ,以及相应的解决办法和思路上进行分析,其具体格式如下: , 风险及危害: , 应对措施: , 非安全代码示例 , 安全代码示例 本规范解释权归运营中心技术小组,属于运营中心为了提供公司研发水平以及质量的一系列措施中的一部分,在后续的版本中将根据具体需要进行修改以及调整。 注1:PMD级别分为5级 Error high 必须修改 Error 不修改的项需要进行说明 Warning high 代码中该项每千行代码不能多于2%; Warning 参考 Information 参考 注2:对于Error级别需要项目组通过以下文字说明: 文件名 代码行数 触发PMD规则 不修改原因 技术小组审核意见 技术小组审核后给出相应的整改意见,对于有争议的问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 ,可直接与运营中心技术小组领导成员沟通。 第2章 要求 气象局项目组的所有java开发人员,编写的代码必须满足第三章的所有规范(每个标题为一个规范)。项目组成员之间每周或每月互相检查对方编写的代码,若发现问题,要求对方及时更正。项目经理应该随时抽查、并最终审查代码,保证代码的规范性。 第3章 java一般性研发规范 3.1 代码格式 3.1.1 包、类、方法的命名规范: , 规范描述: 包,类,方法命名只能为27个英文字符以及数字,不能包括特殊字符例如-, _,$等; 包命名,首字符必须小写; 类命名,首字符必须大写; 方法命名,首字符必须小写; 常量命名,必须全部大写; 变量,以及属性命名,首字符必须小写; 在类中非创建方法其命名应避免与类名一致; 在类中属性的命名应避免与类名一致; 在同一类中属性命令应避免与方法命名一致; 在方法中命名临时变量时应避免与方法的参数名一致; , PMD规则名称: AvoidDollarSigns PackageCase ClassNamingConventions MethodNamingConventions SuspiciousConstantFieldName VariableNamingConventions MethodWithSameNameAsEnclosingClass AvoidFieldNameMatchingTypeName MisleadingVariableName , 规则级别: Error High warn High warn High warn High warn High Error High Error High Error High , 违规示例代码: 1、常量、变量命名 public static final int my_num = 0; //常量应大写 public String MyTest = ""; //变量命名,首字符小写 DataModule DMTest = new DataModule();//变量命名,首字符小写 2、方法命名 public class Foo { public void FooStuff() { } } 3、类命名:首字符应大写 public class foo {} 4、非法使用特殊字符命名 public class Fo$o { // yikes! } 5、非创建方法命名应避免与类名一致 public class MyClass { // this is bad because it is a method public void MyClass() {} // this is OK because it is a constructor public MyClass() {} } 6、方法中临时变量的命名应避免与其参数一致: public void bar(String m_baz) { // Bad int m_boz = 42; // Bad } 7、在类中属性的命名应避免与类名一致: public class Foo extends Bar { // There's probably a better name for foo int foo; } 8、在同一类中属性命名应避免与方法命名一致: public class Foo { Object bar; // bar is data or an action or both? void bar() { } } , 合法代码示例: 1、常量、变量命名: public static final int MY_NUM = 0; // public String myTest = ""; DataModule dmTest = new DataModule(); 2、方法命名:首字符应小写 public class Foo { public void fooStuff() { } } 3、类命名:首字符应大写 public class Foo {} 3.1.2 方法的命名应注意避免与java中具有特殊意义的名称例如equals, hashCode,clone,finalizer等冲突 , 规范描述: 在java中某些方法是具有特殊意义的,例如boolean equals(Object o)是比较两个对象是否相等;int hashCode()取得hash值,主要用于hash表;Object clone()用于复制对象;void finalizer()用于该类实例化的对象释放时系统调用释放该对象使用的资源。这些方法具有固定的形参格式,固定的返回值,不能被其他形式或者用于其他方面的方法override,否则将降低代码可读性,并为代码维护带来隐患。 , PMD规则名称: SuspiciousEqualsMethodName SuspiciousHashcodeMethodName; FinalizeOverloaded; BooleanGetMethodName; , 规则级别: Error High Error High Error High Error High , 违规示例代码: 1、可疑的equals方法命名 public class Foo { public int equals(Object o) { // oops, this probably was supposed to be boolean equals } public boolean equals(String s) { // oops, this probably was supposed to be equals(Object) } } 2、可疑的hashCode命名 public class Foo { public int hashCode(int value) { // oops, this probably was supposed to be hashCode } } , 合法代码示例: 、正确的equals方法命名 1 public class Foo { public boolean equals(Object o) { // oops, this probably was supposed to be boolean equals } } 2、正确的hashCode命名 public class Foo { public int hashCode() { // oops, this probably was supposed to be hashCode } } 注:一般来说override hashCode方法为了避免键值冲突,提高hash表的查询效率,可采用37乘法原则,例如某javabean中包含两个关键属性str1,str2,str3该关键属性不能为空,这其hash值按以下算法获得:str1.hashCode()+str2.hashCode()*37+str3.hashCode()*37*37。 3.1.3 Java bean中取得boolean类型的属性值必须使用is****形式命名 , 规范描述: 对于java bean来说,get***是取得该bean的属性值,set***为设置该bean的属性值,is***是获得该bean中为boolean类型的属性值,这些方法对java bean来说是具有特殊意义,如果命名不规范将导致在使用java bean内置方法时出现取值,或者设值不成功。 , PMD规则名称: BooleanGetMethodName , 规则级别: Error High , 违规示例代码: public boolean getFoo(); // bad , 合法代码示例: public boolean isFoo(); // ok 3.1.4 if,else,while,for等必须使用{} , 规范描述: If,else,while,for等分支循环语句,必须使用{}将业务处理逻辑包含在 内,这样可大大提高代码可读性,有利于后续代码维护。 , PMD规则名称: IfStmtsMustUseBraces WhileLoopsMustUseBraces IfElseStmtsMustUseBraces ForLoopsMustUseBraces , 规则级别: warn High , 违规示例代码: 1、if语句违例代码 if (foo) x++; 2、else语句违例代码 if (foo) x++ else x--; 、while语句违例代码 3 while(x<100) x++; 4、for语句违例代码 for(int i=0;i<10;i++) x++; , 合法代码示例: 1、if语句 if (foo){ x++; } 2、else语句 if (foo){ x++ }else{ x--; } 3、while语句 while(x<100){ x++; } 5、for语句 for(int i=0;i<10;i++){ x++; } 3.1.5 类必须包含在包里,禁止出现无包的类 , 规范描述: 包是java中类所在命名空间,用于类载入时,虚拟机快速定位并查找该类;如果一个无包类,在类载入时,耗时较多,并且很可能无法找到该类。 , PMD规则名称: NoPackage , 规则级别: error High 3.1.6 类和方法必须拥有注释,注释量占总体代码25%以上,类头部,以及 方法头部的注释应符合javadoc标准。 , 规范描述: 注释多少是评价代码质量好坏的一个标准,25%是符合国际上对java注释的标准;对于类头部注释,方法头部注释符合javadoc标准,可java工具自动根据源码生成相应的java帮助文档。对于类头部注释需要包含以下信息:该类的主用功能,作者,以及创建时间等信息;对于方法头部注释需要包含以下信息:该方法的主要功能,以及参数类型含义,返回值类型含义等等。 , 合法代码注释示例 1、类头部注释规范 /** * 实时数据文件解析:读取实时数据文件,对其内容进行解析,生成符合格式以及标准单位的数据集合 * @author wangliuyi * @version 1.0 * @since 2009-05-15 */ public class DataFileParse{ 2、方法头部注释规范 /** * 判断该时间是否在统计时区里面 * @param time long 从实时采集文件中提取的时间,该时间为格林威治时间,单位为毫秒 * @return boolean true:表示该时间在合法的时间区内 false:表示该时间不合法 */ public boolean checkStatTimeZone(long time) 3、属性以及方法内部的注释通过“//”注释 public class GeneralStat implements IStat { //解析数据格式的分隔符号 private String separator = ","; //开始统计序号 private int startNum = 1; 3.2 基本语法 3.2.1 不能随意捕捉异常,原则上谁捕捉谁处理 , 规范描述: Java程序运行过程中产生异常,意味着有错误产生,捕捉该异常,就需要对该异常进行处理:例如 记录 混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载 日志,事务回滚等,如果仅捕获而不处理,人为的屏蔽异常,调用该函数,可能为调用者带来困惑,调用者极可能认为该方法正常运行而做出错误的判断。 一般来说,异常处理机制属于应用程序总体框架的一部分,一个良好的异常处理机制可以避免系统产生的一些不可预测的结果,并提高代码可读性,可维护性,从而提高代码的质量。本规则要对异常处理进行检查,对一些捕捉后不处理,或者直接将该异常抛出等进行预警。 , PMD规则名称: EmptyCatchBlock , 规则级别: Warn High , 违规示例代码: public void doSomething() { try { doSomething……; } catch (IOException ioe) { // 获取异常后没有做任何处理 } } , 合法代码示例: public static int parseInt(String value, int defaultValue) { if (isNull(value)) { return defaultValue; } try { return Integer.parseInt(value.trim()); } catch (Exception ex) { //记录日志 Log.warn(“转换异常”,ex); //异常后返回缺省值 return defaultValue; } } 3.2.2 if,while,try,finally,switch , synchronized , static instantiation 里面应有相应的逻辑处理,不能为空。 , 规范描述: 在if,while,try,finally,switch,synchronized,static Initializer中处理 逻辑部分如果为空,很可能这段代码无任何作用,是段废弃的代码,这段代码的 存在不仅对代码维护带来疑惑,降低了整体的代码质量。 , PMD规则名称: EmptyIfStmt EmptyWhileStmt EmptyTryBlock EmptyFinallyBlock EmptySwitchStatements EmptySynchronizedBlock EmptyStaticInitializer , 规则级别: Warn High , 违规示例代码: 1. if语句中为空 if (foo){ } 2. while语句中为空 while(x<100) { } 3. try,finally中为空 try{ }finally{ } 4. switch中为空 switch(value){ } 5. synchronized中为空 synchronized(this){ } 6. static Initializer为空 static{ } 3.2.3 在处理循环中,不能在程序中人为的改变步长。 , 规范描述: 在循环中对步长变量人为的改变,很有可能丧失对步长的控制,导致运行时出现一些不可预测的结果。该规则是限制开发者对这种场景的使用,毕竟步长在多个地方改变,开发者很容易没有考虑全面,导致在特殊情况下出错。 , PMD规则名称: JumbledIncrementer , 规则级别: Error , 违规示例代码: 1. 上述代码会陷入死循环 public void foo() { for (int i = 0; i < 10; i++) { for (int k = 0; k < 20; i++) { System.out.println("Hello"); } } 3.2.4 将简单类型int,short,float,double等转化成字符串时,需使用 其对应类的toString方法。 , 规范描述: 将java中简单类型转换成字符串时,如果采用先转换成对应的类型的对象,然后通过值对象转换成字符串,该过程将产生两个对象的创建,而直接采用对应类型的toString方法,只产生一个对象的创建,其效率是前者的两倍。 , PMD规则名称: UnnecessaryConversionTemporary , 规则级别: Error High , 违规示例代码: 1、 整形转字符 int value=1; String v=new Integer(value).toString(); 2、 短整形转字符 short value=1; String v=new Short(value).toString(); 3、 浮点转字符 float value=1.2f; String v=new Float(value).toString(); 4、 双精度浮点转字符 double value=1.2d; String v=new Double(value).toString(); , 合法代码示例: 1、 整形转字符 int value=1; String v= Integer.valueOf(value); 2、 短整形转字符 short value=1; String v= Short.valueOf( value); 3、 浮点转字符 float value=1.2f; String v= Float.valueOf( value); 4、 双精度浮点转字符 double value=1.2d; String v= Double.valueOf(value; 3.2.5 javaBean中hashCode,以及equals方法必须同时override。 , 规范描述: HashCode是生成hash值,可用于hash表中主键的查找,equals是比较两个对象是否相等,缺省的hashCode以及equals只能针对同一引用的对象,如果为不同的引用的对象,虽然其值是相等,但使用hashCode却是不同的值,而使用equals返回的也是false。在某些场合中,例如将某javabean对象作为hash表的主键值,或者判断某对象是否在集合中,如果不实现hashCode,以及equals 会得到不可预测的结果。 , PMD规则名称: OverrideBothEqualsAndHashCode , 规则级别: Error High , 违规示例代码: //该AgcDataInfo没有override equals方法 public class AgcDataInfo { Public AgcDataInfo(String planUnitNo) { if(planUnitNo!=null) this.planUnitNo = planUnitNo; } //机组名称 String planUnitNo=””; /** * 生成hash值 */ public int hashCode() { return this.getPlanUnitNo().hashCode(); } /**自动生成get,set方法 public String getPlanUnitNo() { return planUnitNo; } public void setPlanUnitNo(String planUnitNo) { if(planUnitNo!=null) this.planUnitNo = planUnitNo; } } public void main(String[] args) { Collection v=new Vector(); Map map=new Hashtable(); AgcDataInfo t1=new AgcDataInfo(“test”); AgcDataInfo t2=new AgcDataInfo(“test”); v.add(t1); map.put(t1,“test“); map.put(t2,“test“); //false而不是true System.out.println(v.contains(t2)); //2而不是1 System.out.println(map.size()); } , 合法代码示例: public class AgcDataInfo { Public AgcDataInfo(String planUnitNo) { if(planUnitNo!=null) this.planUnitNo = planUnitNo; } //机组名称 String planUnitNo=””; /** * 比较等式,比较值为下达时间,下达功率,机组名称 */ public boolean equals(Object o) { if (o instanceof AgcDataInfo) { AgcDataInfo data = (AgcDataInfo) o; return his.getPlanUnitNo().equals(data.getPlanUnitNo()); } return false; } /** * 生成hash值 */ public int hashCode() { return this.getPlanUnitNo().hashCode(); } /**自动生成get,set方法 public String getPlanUnitNo() { return planUnitNo; } public void setPlanUnitNo(String planUnitNo) { if(planUnitNo!=null) this.planUnitNo = planUnitNo; } } public void main(String[] args) { Collection v=new Vector(); Map map=new Hashtable(); AgcDataInfo t1=new AgcDataInfo(“test”); AgcDataInfo t2=new AgcDataInfo(“test”); v.add(t1); map.put(t1,“test“); map.put(t2,“test“); //true System.out.println(v.contains(t2)); //1 System.out.println(map.size()); } 3.2.6 懒式方式创建对象:不能采用双检查惯用法 , 规范描述: 双检查一般用于c,c++懒式方式获得资源时惯用模式,但在java中该模式是不适用的,因为java创建对象时,先将对象创建后,直接将指针赋予给变量,然后才进行后续的初始化,在初始化这段空白期中,如果另外的线程获得该对象的引用,调用该对象,会产生一些不可预测的结果。 , PMD规则名称: DoubleCheckLock , 规则级别: Error High , 违规示例代码 public class Foo { Object baz; Object bar() { if(baz == null) { //baz may be non-null yet not fully created synchronized(this){ if(baz == null){ baz = new Object(); } } } return baz; } } , 合法代码示例: public class Foo{ Object baz; Object bar() { synchronized(this){ if(baz == null){ baz = new Object(); } } return baz; } } 3.2.7 不能在finally中返回值。 , 规范描述: finally中是必须执行的程序块,如果在里面返回,则表示该方法返回值只 能为这个,其他地方返回值可能无效。 , PMD规则名称: ReturnFromFinallyBlock , 规则级别: Error High , 违规示例代码: public int foo(String value) { try { return Integer.parseInt(value); } catch (Exception e) { return 0;; } finally { return -1; // Very bad. } } , 合法代码示例: public int foo(String value) { int ret=0; try { ret= Integer.parseInt(value); } catch (Exception e) { ret= 0; } finally { //处理其他事宜 …… } return ret; // Very good. } 3.2.8 Boolean实例化时,应用使用Boolean.valueOf,Boolean.TRUE, Boolean.FALSE。 , 规范描述: 采用Boolean.valueOf,Boolean.TRUE,Boolean.FALSE进行实例化具有更高的效率。 , PMD规则名称: BooleanInstantiation , 规则级别: Error High , 违规示例代码: Boolean bar = new Boolean("true");//效率较低 , 合法代码示例: // just do a Boolean bar = Boolean.TRUE; Boolean buz = Boolean.valueOf(false); // just do a Boolean buz = Boolean.FALSE; 3.2.9 Integer,Byte,Short,Long等实例化时,应用使用valueOf , 规范描述: Integer,Byte,Short,Long实例化时使用valueOf具有更高的效率。 , PMD规则名称: IntegerInstantiation ByteInstantiation ShortInstantiation LongInstantiation , 规则级别: Error High , 违规示例代码: Integer v=new Integer(1); Byte v=new Byte(1); Short v=new Short(1); Long v=new Long(1); , 合法代码示例: Integer v= Integer.valueOf(1); Byte v=new Byte.valueOf(1); Short v= Short.valueOf(1); Long v= Long.valueOf(1); 3.2.10 对于多个if语句嵌套的情况下能够整合尽量整合。 , 规范描述: 对于多个if语句嵌套的情况下能够整合必须根据情况整合。 , PMD规则名称: CollapsibleIfStatements , 规则级别: Error , 违规示例代码: void bar() { if (x) { if (y) { // do stuff } } } , 合法代码示例: void bar() { if (x&y) { // do stuff } } 3.2.11 override function,不能只有super.function语句,否则视为无效 代码 , 规范描述: Over ride function则表示为该方法定义新的行为,如果仅仅super.function(),则没有任何意义,该处代码视为废弃代码。。 , PMD规则名称: UselessOverridingMethod , 规则级别: Error High , 违规示例代码: public class Foo { public void foo(String bar) { super.foo(bar); //Why bother overriding? } , 合法代码示例: 3.2.12 Collection.toArray的注意事项。 , 规范描述: 对于Collection接口来说,使用toArray转数据时,如果没有指明类型,将返回Object[],而不能使用类似(Integer[])list.toArray()进行强转成其他类型的数组,需要类似toArray(new Integer[list.size()])方式进行转换。 , PMD规则名称: ClassCastExceptionWithToArray , 规则级别: Error High , 违规示例代码: Collection c=new ArrayList(); Integer obj=new Integer(1); c.add(obj); // this would trigger the rule (and throw a ClassCastException if executed) Integer[] a=(Integer [])c.toArray(); , 合法代码示例: Collection c=new ArrayList(); Integer obj=new Integer(1); c.add(obj); // this wouldn't trigger the rule Integer[] b=(Integer [])c.toArray(new Integer[c.size()]); 3.2.13 对于BigDecimal方法,应避免使用float值,double值进行创建, 应使用字符串形式创建。 , 规范描述: 对于BigDecimal,直接使用float,double创建时,因为精度不同会发生变化,例如0.1,会变成.1000000000000000055511151231257827021181583404541015625,这样会导致业务计算造成偏差。 , PMD规则名称: AvoidDecimalLiteralsInBigDecimalConstructor , 规则级别: Error High , 违规示例代码: // this would trigger the rule BigDecimal bd=new BigDecimal(1.123); , 合法代码示例: // this wouldn't trigger the rule BigDecimal bd=new BigDecimal("1.123"); 3.2.14 String,BigDecimal,BigInteger等值类型调用replace,add等方法 的注意事项。 , 规范描述: String,BigDecimal,BigInteger为值类型,当调用replace,replaceAll对字符串中替代函数,BigDecimal,BigIneger等add运算函数,会生成一个结果值对象返回,而不是修改本身调用者对象,该规则正是在这方面进行检查。 , PMD规则名称: UselessOperationOnImmutable , 规则级别: Error High , 违规示例代码: BigDecimal bd=new BigDecimal(10); bd.add(new BigDecimal(5)); // bd仍然为10 , 合法代码示例: BigDecimal bd=new BigDecimal(10); bd = bd.add(new BigDecimal(5)); // bd为15 3.2.15 需要注意的引起NullException的语句。 , 规范描述: 对空指针对象进行操作时,会抛出NullException异常,该规则则是在代码编写以及代码健全性上避免这些导致空指针异常的场景,规则如下: 使用equals时,常量应该放在前面,例如常量.equals(对象); 判非空:string!=null&&string.length()>0; 判空: string==null||string.length()<=0; 执行类似equals语句:a!=null&&a.equals(b); 禁止使用equals(null)方式 , PMD规则名称: MisplacedNullCheck UnusedNullCheckInEquals BrokenNullCheck , 规则级别: Error High , 违规示例代码: 1、 空指针检查错位 if (a.equals(baz) && a != null){ „„ }; if (a.equals(baz) || a == null){ „„ }; 2、 无用的空指针检查 if (a!=null && b.equals(a)) { // 该处虽然对a对象进行了检查,但没有对b进行检查 //whatever } 3、 常见的判空,判非空代码编写上的错误 //判非空,却使用了|| if (string!=null || !string.equals("")){ return string; } //判空却用了&& if (string==null && string.equals("")){ return string; } 4、 比较对象是否为空,使用了equals str.equals(null) , 合法代码示例: 1、 空指针检查应放在前面 if (a != null && a.equals(baz)){ „„ }; if (a == null ||a.equals(baz)){ „„ }; 2、 已检查的对象作为调用者 if (a!=null && a.equals(method1)) { // 该处虽然对a对象进行了检查,但没有对mothod1进行检查 //whatever } 3、 常见的判空,判非空代码编写上的错误 //判非空用了&& if (string!=null && !string.equals("")){ return string; } //判空用|| if (string==null || string.equals("")){ return string; } 4、 比较对象是否为空,使用了== If(str==null) 3.2.16 ResultSet使用next时,需要判断是否具有记录再进行一下步操作。 , 规范描述: java对数据库进行查询操作,取得结果集合ResultSet对象,使用next,让游标定位到下一行,下一行不存在时,next()返回false,该规则这是强制对下一行是否用记录进行判断,根据结果进行后续操作。 , PMD规则名称: CheckResultSet , 规则级别: Error High , 违规示例代码: Statement stat = conn.createStatement(); ResultSet rst = stat.executeQuery("SELECT name FROM person"); rst.next(); // what if it returns a 'false' ? String firstName = rst.getString(1); , 合法代码示例: // This is appropriate... Statement stat = conn.createStatement(); ResultSet rst = stat.executeQuery("SELECT name FROM person"); if (rst.next()) { String firstName = rst.getString(1); } else { // here you deal with the error ( at least log it) } 3.2.17 字符串使用相应的规则。 , 规范描述: 字符串是应用服务器创建最多的对象之一,对字符串操作按照合适的规则进行编写,会极大增加应用服务整体性能,以下是字符串操作相应的规则: 字符串比较需要使用equals,而不是==,~=,因为==只是对同一引用的对象比较认为相同,而不比较对象里内容是否相等; 使用StringBuffer代替string+string+string进行字符串相加,n个字符相加,如果直接用“+“号,会新产生n-1个StringBuffer对象,以及n-1个String对象,而用StringBuffer只会产生1个String,1个StringBuffer对象。 使用equalsIgnoreCase() 替代 toUpperCase/toLowerCase().equals(),这样减少一个对象的创建,效率更高。 使用StringBuffer.length()替代StringBuffer.toString().length(),这样减少一个对象的创建,效率更高。 对于String对象禁止使用string.toString(),本身是String对象,这样调用效率低下,而且由于string没有判空,很可能导致空异常的风险。 , PMD规则名称: UseEqualsToCompareStrings UseStringBufferLength UnnecessaryCaseChange UseStringBufferLen StringToString , 规则级别: Error High , 违规示例代码: 1、 字符串比较 if(str1==str2){ „„ } 2、 字符串相加 String str=str1+str2+str3+str4; 3、 大小写不敏感字符串比较 str1.toUpperCase().equals(str2.toUpperCase()); 4、 取StringBuffer的长度 StringBuffer strbuf=new StringBuffer(); strbuf.append(“test1”); strbuf.append(“test2”); int length=strbuf.toString().length(); 5、 字符串违例转字符串 String params=request.getParameter(“test”).toString(); , 合法代码示例: 1、 字符串比较 if(str1.equals(str2)){ „„ } 2、 字符串相加 StringBuffer strbuf=new StringBuffer(); strbuf.append(str1); strbuf.append(str2); strbuf.append(str3); strbuf.append(str4); String str=strbuf.toString(); 3、 大小写不敏感字符串比较 str1. equalsIgnoreCase (str2); 4、 取StringBuffer的长度 StringBuffer strbuf=new StringBuffer(); strbuf.append(“test1”); strbuf.append(“test2”); int length=strbuf.length(); 5、 其他 String params=request.getParameter(“test”); 3.2.18 禁止直接调用 System.gc(),System.getRuntime().gc(),System.runFinalization()。 , 规范描述: System.gc(),System.getRuntime().gc(),System.runFinalization()等操作会触发java虚拟机进行垃圾回收,它将暂停业务的处理,进行回收处理,如果此时应用服务器正在处理高峰器,将导致不可预测的后果。Java虚拟机自动回收机制具有很高的效率,手动方式去触发,反而导致效率降低。该规则则是禁止手动触发垃圾回收。。 , PMD规则名称: DoNotCallGarbageCollectionExplicitly , 规则级别: Error High 3.2.19 finalize相应的规则。 , 规范描述: 每个类的finalize是由java虚拟机垃圾回收时,由系统自动调用的方法,用于释放各类资源。对应用服务来说,对于文件,数据库等重要级别较高的系统资源,一般来说用完即释放,只有非重要性的需要手工释放的资源在finalize中释放,该规则这是针对finalize的编写制定的规范: finalize函数override时,不能为空,或者只包含super.finalize(); 不能创建与finalize函数相近的函数,例如finalize(int),系统不会自动调用该函数; finalize函数必须含有super.finalize()语句,对父类使用的资源进行释放; Finalize函数访问范围应为protected; 尽量避免直接调用finalize函数。 , PMD规则名称: EmptyFinalizer FinalizeOnlyCallsSuperFinalize FinalizeOverLoaded FinalizeDoesNotCallSuperFinalize AvoidCallingFinalize , 规则级别: Error High 3.2.20 禁止在代码中使用System.out,ex.printStackTrace打印日志。 , 规范描述: System.out.println,System.out.print是在屏幕中打印信息,ex.printStackTrace()是在屏幕上打印堆栈信息。屏幕上打印信息具有实时性,事后无法跟踪,这类打印日志一般在调试时使用较多,导致代码中该类命令满天飞,严重影响了代码的维护工作。 , PMD规则名称: SystemPrintln AvoidPrintStackTrace , 规则级别: rror High E , 违规示例代码: public int foo(String value) { int ret=0; System.out.println(“开始进行转整数处理”); try { ret= Integer.parseInt(value); System.out.println(“成功完成转整数处理”); } catch (Exception e) { e.printStackTrace(); ret= 0; } return ret; // Very good. } , 合法代码示例: public int foo(String value) { int ret=0; log.info(“开始进行转整数处理”); try { ret= Integer.parseInt(value); log.info(“成功完成转整数处理”); } catch (Exception e) { Log.error(“转整数异常”,e); ret= 0; } return ret; // Very good. } 3.2.21 系统资源释放(谁创建的,谁关闭) , 规范描述: 在java中系统资源需要手工释放,例如涉及数据库资源例如Connection,Statement,PrepareStatement,ResultSet,涉及文件资源FileOutStream,FileInStream等资源,这些资源如果在使用完后,必须在释放,否则将影响这个操作系统的运行,因此必须在finally中关闭,其原则为谁创建的,谁关闭。 , PMD规则名称: ResourceClose , 规则级别: Error High , 违规示例代码: 1、 读文件流关闭 Properties props = new Properties(); try { //第一种形式,可能因为异常无法关闭 FileInputStream input = new FileInputStream(CONFILENAME); props.load(input); //第二种形式,没有想到关闭资源 props.load(new FileInputStream(CONFILENAME)); } catch (Exception ex) { throw new ConfigErrorException("读取配置文件异常"); } 2、 写文件流关闭 File file = new File(FILENAME); try { //第一种形式,可能因为异常无法关闭 FileOutputStream outputStream = new FileOutputStream(file); props.save(outputStream, "test"); outputStream.close(); //第二种形式,没有想到关闭资源 props.save(new FileOutputStream(file), "test"); } catch (Exception ex) { throw new ConfigErrorException("保存配置文件异常"); } 3、 数据库资源的关闭 // This is appropriate... Statement stat = conn.createStatement(); ResultSet rst = stat.executeQuery("SELECT name FROM person"); if (rst.next()) { String firstName = rst.getString(1); } else { // here you deal with the error ( at least log it) } //可能因为异常没有关闭 rs.close(); stat.close(); conn.close(); , 合法代码示例: 1、 读文件流关闭 FileInputStream input = null; Properties props = new Properties(); try { input = new FileInputStream(CONFILENAME); props.load(input); } catch (Exception ex) { throw new ConfigErrorException("读取配置文件异常"); } finally { if (input != null){ try { input.close(); } catch (Exception ex) { } } } 2、 写文件流关闭 File file = new File(FILENAME); FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(file); props.save(outputStream, "test"); } catch (Exception ex) { throw new ConfigErrorException("保存配置文件异常"); } finally { if (outputStream!= null){ try { outputStream.close(); } catch (Exception ex) { } } } 3、 数据库资源释放 Connection con=null; Statement stat=null; ResultSet rs=null; try { con=createConnetion(); stat = conn.createStatement(); ResultSet rst = stat.executeQuery("SELECT name FROM person"); if (rst.next()){ String firstName = rst.getString(1); }else{ // here you deal with the error ( at least log it) } catch(SQLException ex) { if(rs!=null){ try{ rs.close(); }catch(Exception ex) { } } rs =null; if(stat!=null){ try{ stat.close(); }catch(Exception ex) { } } stat =null;; if(conn!=null){ try{ conn.close(); }catch(Exception ex) { } } conn=null; } 3.2.22 使用Clone时相应的规则。 , 规范描述: 复制是表示将一个对象复制成另外的对象,一般来说,复制是为了生成一个对象,该对象的内容与原对象相同,但对该对象操作不影响原对象的值,复制可分为深复制,以及浅复制,要实现深复制,由于Collection,Map等类型属性需要手工进行编程实现。以下为复制的规则: Override Clone时,必须执行super.clone(); 实现Clone方式时,需要抛出CloneNotSurportException; 所有实现Clone方法的类,必须实现Cloneable接口 , PMD规则名称: ProperCloneImplementation CloneThrowsCloneNotSupportedException CloneMethodMustImplementClonable , 规则级别: Error High , 合法代码示例: 3.2.23 java Bean类必须实现Serialize接口。 , 规范描述: Serialize是java bean重要的接口,其作用是将一个对象序列化成一个文件,或者网络字节序传递到网络的另外一方进行执行以及传值,对java bean进行序列化是一个良好的习惯,该规则则是对java bean序列化进行检查。 , PMD规则名称: BeanMembersShouldSerialize , 规则级别: Warn High 3.2.24 比较对象相等应使用equals,而不是==。 , 规范描述: 在java中使用==是比较两个变量是否是同一个对象的引用,而不是两个对象的比较,如果要比较,则需要该类实现equals方法,实现比较的业务逻辑,采用equals进行比较。 , PMD规则名称: CompareObjectsWithEquals , 规则级别: Error High , 违规示例代码: Integer t1=Integer.valueOf(1); Integer t2=Integer.valueOf(1); //该处返回值是false System.out.println(t1==t2); , 合法代码示例: Integer t1=Integer.valueOf(1); Integer t2=Integer.valueOf(1); //该处返回值是false System.out.println(t1.equals(t2)); 3.2.25 Array数组拷贝应使用System.arrayCopy。 , 规范描述: 对于数组来说System.arrayCopy()执行效率比数组中对象依次拷贝要快很多,如果数组很大的情况下,其效率更明显。 , PMD规则名称: , 规则级别: Error High , 违规示例代码: String[] strs1={“1”,”2”, “3”,”4”}; String[] strs2=new String[4]; for(int i=0;i
, 安全代码示例 <% String mofWindowId=XSSCheck.getParameter(request,”mofWindowId”); %> 注:XSSCheck为公用工具类,用于XSS检查,其getParameter实现逻辑如下: 1、通过参数名称,从请求中取得参数值。 2、将&,<,>,’,”转义: & -> & < -> ⁢ > -> > “ -> " ‘ -> ´ 3、返回安全的字符串。 4.2 违反信任边界规则(Trust Boundary Violation) , 风险及危害 一个受信任的边界可以被认为是由系统划出的边境,例如 session,attribute,aplication,数据库,文件等在服务端存储边界都认为是受信任的。反之来来自http的post,或者get方式取得参数值是不受信任的。凡是将非受信任边界的参数转入到受信任的边界内,需要对参数值进行检查,否则造成信任边界违例,当开发者直接操作受信边界内部的参数时会认为该参数是安全的,而造成安全隐患,例如脚本注入,XSS攻击等。 , 应对措施 开发者要保证代码的安全性,当参数信任边界切换的时候,对参数值进行检查,检查其内容里是否用非法脚本信息: 1( 过滤或转换用户提交数据中的HTML代码。 2( 限制用户提交数据的长度 , 非安全代码示例 String dsn = request.getParameter("DSN"); String sql = request.getParameter("SQL"); if (sql == null) { sql = ""; } dsn = (String) session.getAttribute("SqlHelper.DSN"); } else { session.setAttribute("SqlHelper.DSN", dsn); } , 安全代码示例 String dsn = XSSCheck.getParameter(request,"DSN"); String sql = request.getParameter("SQL"); if (sql == null) { sql = ""; } dsn = (String) session.getAttribute("SqlHelper.DSN"); } else { session.setAttribute("SqlHelper.DSN", dsn); } fe Reflection) 4.3 不安全的反射(Unsa , 风险及危害 攻击者能够建立一个不可预测的、贯穿应用程序的控制流程,使得他们可以潜在地避开安全检测。攻击者能够建立一个在开发者意料之外的、不可预测的控制流程,贯穿应用程序始终。这种形式的攻击能够使得攻击者避开身份鉴定,或者访问控制检测,或者使得应用程序以一种意料之外的方式运行。如果攻击者能够将文件上传到应用程序的classpath或者添加一个classpath的新入口,那么这将导致应用程序陷入完全的困境。无论是上面哪种情况,攻击者都能使用反射将新的、多数情况下恶意的行为引入应用程序。 , 应对措施 开发者可以定制一份白名单,通过关键字关联需要实例化的类,http请求中传递是不是实际的类名,而是关键字,开发者得到关键字后在白名单中寻找需要的信息,进行实例化。 , 非安全代码示例 String className = request.getParameter("classname"); if ((className != null)&& ((className = className.trim()).length() != 0)) { // Attempt to load class and get its location. try { ProtectionDomain pd = Class.forName(className).getProtectionDomain(); if (pd != null) { CodeSource cs = pd.getCodeSource(); , 安全代码示例 String classNameKey = request.getParameter("classname"); String className=WhiteList.get(classNameKey); if ((className != null)&& ((className = className.trim()).length() != 0)) { // Attempt to load class and get its location. try { ProtectionDomain pd = Class.forName(className).getProtectionDomain(); if (pd != null) { CodeSource cs = pd.getCodeSource(); 注1:WhiteList.get其具体实现如下: 1、从描述白名单的文件中,读出白名单列表; 2、根据传入的关键值寻找该白名单的真实值; 3、返回该值,如果没有找到,抛出异常。 4.4 SQL 注入(SQL Injection) , 风险及危害: SQL注入是一种常见攻击方式,由于开发者采用sql拼凑的方式,用来自网 络中不安全的参数形成sql语句访问数据库,攻击者常常采用该漏洞组合成非法 的sql语句,使得信息泄露,访问到本来没有权限查看的内容或者直接破坏数据 库信息等。发生SQL Injection有以下几种方式: 一、进入程序的数据来自不可信赖的资源。 二、数据用于动态构造一个SQL查询。 , 应对措施: 一、开发者可以采用带参方式访问sql语句访问数据库,在java中即采用 PreparedStatement的方式访问数据库。 二、如果开发者一定要使用sql拼凑的方式访问数据,对字符串要检查并过 滤单引号’,对于可能为整形或者浮点类型参数,要先转整形,或者浮点,再进 行拼凑。 , 非安全代码示例 String userid= (String)session.getAttribute("classname"); String param1= request.getParameter(“param1”); StringBuffer strbuf=new StringBuffer(); strbuf.append(“select * from table1 where userid=”); strbuf.append(userid); strbuf.append(“ and param1=’”).append(param1).append(“’”); String sql=strbuf.toString(); //当param1为 test’ or 1=1 那么这条语句就为 select * from table1 where userid=$userid and param1=’test’ or 1=1这样查询出来的数据就超越了这个用户访问的范围。 , 安全代码示例 方法一:采用PreparedStatement访问数据库。 String userid= (String)session.getAttribute("classname"); String param1= request.getParameter(“param1”); StringBuffer strbuf=new StringBuffer(); String sql= “select * from table1 where userid=? and param1=?”; 方法二:检查并过滤特殊字符 String userid= (String)session.getAttribute("classname"); String param1= request.getParameter(“param1”); StringBuffer strbuf=new StringBuffer(); strbuf.append(“select * from table1 where userid=”); strbuf.append(userid); strbuf.append(“ and param1=’”) .append(SqlInjectCheck.checkStringValue(param1)).append(“’”); String sql=strbuf.toString(); 注:SqlInjectCheck.checkStringValue是公用函数,其实现如下: 1、将’转化成´ 2、返回字符串。 4.5 系统信息泄露(System Information Leakage) , 风险及危害: JSP中出现HTML注释(System Information Leakage:HTML Comment in JSP),攻击者可以通过html的注释得到用于攻击的信息。 , 应对措施: 应该使用JSP注释代替HTML注释。(JSP注释不会被传递给用户)。 , 非安全代码示例 , 安全代码示例 <%//此处是取得系统信息的注释%> 4.6 资源注入(resource injection) , 风险及危害: 允许用户可以通过输入来控制资源标识符,会让攻击者有能力访问或修改被保护的系统资源。 发生resource injection有以下两种方式: 1. 攻击者可以指定已使用的标识符来访问系统资源。例如,攻击者可以指定用来连接到网络资源的端口号。 2. 攻击者可以通过指定特定资源来获取某种能力,而这种能力在一般情况下是不可能获得的。 , 应对措施 开发者可以定制一份白名单,通过关键字关联需要资源内容,http请求中传递是不是实际的资源内容,而是关键字,开发者得到关键字后在白名单中寻找需要的信息,进行后续操作。 , 非安全代码示例 String dsn = request.getParameter("DSN"); DataSource ds = (DataSource) ctx.lookup(dsn); , 安全代码示例 String dsnKey = request.getParameter("DSN "); String dsn =WhiteList.get(dsnKey); DataSource ds = (DataSource) ctx.lookup(dsn);
本文档为【Java开发规范&#40;公司规范&#41;】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_963767
暂无简介~
格式:doc
大小:116KB
软件:Word
页数:63
分类:
上传时间:2018-04-10
浏览量:59