初中生图片大全可爱:轻量级J2EE程序开发规范

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 19:57:58
文档编号:ACCA-PRJ-RJBM-JAVA程序编写规范-01
轻量级J2EE程序开发规范
1. 开发环境
IDE: JBUILDER2008 , 或 Eclipse3.3以上
JDK & JRE :      1.5 及以上版本
开发时使用的server:Tomcat5.5及以上版本 JBOSS4.3及以上版本
源码字符集: UTF8
2. 技术标准
JAVA Standard Edition:              JAVA SE5.0
JAVA Enterprise Edition:             JAVA EE5.0
3. 对象设计规范
对象设计是系统和程序设计阶段的重要一环,通过一份比较完善的对象设计文档,程序员就可以开始编码。
对象设计输入:用例规约,补充规约,系统架构文档,用户认可的界面Demo
对象设计输出:Logical View,系统架构文档
Logical View 形式要求:
1、按照用户最终的URL层次划分,例如:cn—com—acca—modules
2、对象之间的关系可以有几类:  泛化、聚集、依赖
3、每个对象需要有注释说明该对象主要功能和属性
4、列出该对象中定义的所有方法和属性,并对每一个方法和属性有比较详细的说明,例如:如果定义一个查询方法,要说明该方法的输入输出、返回参数,以及查询方法等。
4.1 系统文件命名约定
文件类型
命名规则
Scripts脚本文件
以一个英文单词来描述,全部小写。例如:date.js
JSP文件
可由一个或者多个英文单词组成,不可缩写,第一个单词的要小写,第二个以后单词的首字母要大写。下面列出常用的JSP页面的命名规则:
查询页面:[entity]Query.jsp
数据列表页面:[entity]List.jsp
数据明细页面:[entity]Detail.jsp
表单页面:[entity]Form.jsp
(一般建议将添加页面和修改页面分为两个独立的jsp页面)
添加页面:[entity]Add.jsp
修改页面:[entity]Update.jsp
业务处理页面: [entity] [operation].jsp 如stkApp.jsp
发现在此未定义的页面类型,需要在此添加该类型页面的命名规则。
Spring Context文件
以”context”做前缀,模块名做后缀,中间用”-“分隔:
spring-context-[module].xml
Struts Validate 文件
以”struts-validate”做前缀,模块名做后缀,中间用”-”分隔:
struts-validate-[module].xml
Struts Config 文件
以”struts-config”做前缀,模块名做后缀,中间用”-”分隔:
struts-config-[module].xml
SQL配置文件
以”sql”做前缀,模块名做后缀,中间用”-“分隔:
sql-[module].properties
DAO接口
[Entity]Dao.java
DAO接口实现类
[Entity]DaoImpl.java
Entity类
以该Entity的名称命名,[Entity].java,例如:Order.java
Hibernate Mapping文件
以该Entity的名称命名,[Entity].hbm.xml,例如:Order.hbm.xml
Exception类
以该异常的简短描述做前缀,不可缩写,以”Exception”做后缀,例如:CanNotChangeCancelledOrderException.java
模块内部接口
一个模块只有一个内部接口的,以模块名做前缀,以” Service”做后缀:[Module]Service.java
否则以模块内子模块名为前缀:[SubModule]Service.java
模块内部接口实现类
一个模块只有一个内部接口的,以模块名做前缀,以”ServiceImpl”做后缀:[Module]ServiceImpl.java
否则以模块内子模块名为前缀:[SubModule]ServiceImpl.java
外部接口
一个模块只有一个外部接口的,以模块名做前缀,以” Manager”做后缀:[Module]Manager.java
否则以模块内子模块名为前缀:[SubModule] Manager.java
资源文件
一个模块只有一个资源文件(不考虑国际化)的,以如下形式命名:[Module]Resources.properties。如果需要国际化,则对于每个资源文件的每种Locale版本,以如下形式命名:[Module]Resources_[Locale].properties,例如:AdminResources_zh_CN.properties
外接口实现类
一个模块只有一个外部接口的,以模块名做前缀,以”ManagerImpl”做后缀:[Module]ManagerImpl.java
否则以模块内子模块名为前缀:[SubModule] ManagerImpl.java
Action类
以模块名作前缀,以”Action”做后缀,中间加Action的描述,例如: UserQueryAction, UserAddAction
Form类
以”Form”做后缀,前面加Form的描述,例如:
UserForm
命名时应始终采用完整的英文描述符。在设计阶段就严格按照命名规范进行命名,在编码阶段,程序员要按照设计阶段的结果报告对类(接口)和方法以及公共属性进行命名,不能私自修改。
a)         使用可以准确说明类(接口)/方法/属性的完整的英文描述符,例如agentInfo,尽量少用缩写(有些缩写已为人们广泛接受,可以方便使用),如果一定要用,要谨慎地使用,而且要给出缩写列表。缩写的字母在变量或类名中使用第一个字母大写,其余字母小写的方法。例如:JdbcDao,JmsTemplate
b)        尽量采用该领域术语。
c)         采用大小写混合,提高名字的可读性。一般用小写字母,但是类和接口的名字的首字符要大写,其余小写。任何中间单词的首字母应该大写。
d)        避免使用下划线作为名字的首字母。
e)         对于属性的命名,如果属性是数组或者列表这样集合的字段,命名时需要使用复数来表示它们代表多值。例如:orderItems。
f)         对于作用域跨越10行以上的变量名称不能少于4-6个字符号,除循环变量,累加变量外不得使用如同i, j, k等名称的变量。
包名
说明
com.acca.common.business
l         com.acca.common.business.dao
通用的进行数据访问的类
l         com.acca.common.business.entity
实体类(可持久化对象)的基类
l         com.acca. common.business.exception
异常类的基类
l         com.acca.common.manager
外部接口及其实现类的基类
l         com.acca.common.service
内部接口及其实现类的基类
com.acca.common.resource
与读取资源文件相关的类和文件
com.acca.common.util
与具体项目无关的工具类
com.acca.common.valueobject
web层与business层交互的值对象
com.acca.common.web
l         com.acca.common.web.action
Action类的基类
l         com.acca.common.web.form
ActionForm类的基类
l         com.acca.common.web.filter
通用的filter类
l         com.acca.common.web.plugin
通用的plugin类的基类
l         com.acca.common.web.servlet
通用的servlet
l         com.acca.common.web.listener
通用的listener的基类
com.acca.page
l         com.acca.page.service
与分页显示相关的service接口及实现类
l         com.acca.page.web.action
与分页显示相关的action类
l         com.acca.page.web.form
与分页显示相关的ActionForm类
com.acca.[project]
与[project]相关的类
com.acca.[project].common
与[project]相关的通用类或者基类,下面可以在分business,web等详细的包。另外,所有项目相关的实体类(entity)和hibernate mapping文件都要存放于com.acca.[project].common.entity
com.acca.[project].common.entity
所有项目相关的实体类(entity)和hibernate mapping文件
com.acca.[project].[module]
每个[project]的每个[module]模块相关的类
com.acca.[project].[module].business
l         com.acca.[project].[module].business.manager
[module]中外部接口与实现类
l         com.acca.[project].[module].business.resource
[module]中所有资源文件
l         com.acca.[project].[module].business.service
[module]中内部接口与实现类
l         com.acca.[project].[module].business.exception
[module]中的异常类
com.acca.[project].[module].web
l         com.acca.[project].[module].web.action
[module]中的Action类
l         com.acca.[project].[module].web.action
[module]中的ActionForm类
com.acca.[project].[module].valueobject
[module]中的VO类
下的文件
在4.2.2中说明的所有package都需要存放于工程目录的src文件夹下。而在src这一级根目录上,也就是我们通常所说的项目的classpath下存放的通常为下列文件:
文件名
说明
ApplicationResources.properties
不属于任何模块的或者多个模块公用的资源信息
Hibernate.cfg.xml
Hibernate配置文件,指定系统中所有hibernate实体映射文件的路径
Hibernate.properties
Hibernate配置文件,指定hibernate的数据库连接信息
Log4j.properties
如果使用log4j作为日志框架,此处指明对于该工程log4j的配置
4.2.4      Class 的命名
Class 的名字必须由大写字母开头而其他字母都小写的单词组成
例:public class ReportProgressEntryPage
变量的命名
变量的名字必须用一个小写字母开头,后面的单词用大写字母开头。
变量的命名根据其作用域的不同而有所区别。
l         模块级变量
对模块级的变量命名采用 自解释性名称
例: public class CustomizeInfoRetrieve {
protected String[] postNames
private boolean cookieIsAdmin
private HtmlPage page


}
l         对象变量
对象变量命名采用以被引用对象的相关名称命名,并使其具有自解释性
例:private Vector employeeVector = new Vector();
License license = new License();
l         数组的命名
数组应该总是用下面的方式来命名:
byte[] buffers;
而不是:
byte buffers[];
有一些常用方法,例如增加纪录、查询纪录等,可以采用统一命名。
l         增加纪录:add[Entity] ()
l         修改纪录:update[Entity] ()
l         删除纪录:delete[Entity] ()
l         获取单个对象 :get[Entity]()
l         按照查询语句获取List:query[Entity]()
l         按照某一个条件获取list:query[Entity]By[param] ()
l         获取所有对象列表:queryAll[entity]()
l         设置某些属性值:set[Property] ()
l         得到某些属性值:get[Property] ()
命名约定 示例
l         实参/ 参数
使用传递值/对象的完整的英文描述符,可能要在名字之前加上 a 或 an 前缀。重要的是选择一种并坚持用它。 例:aCustomer, anAccount
l         字段/ 属性
字段采用完整的英文描述,第一个字母小写,任何中间单词的首字母大写。 例:firstName, lastName, warpSpeed
l         布尔型的获取成员函数
所有的布尔型获取函数必须用单词 is 做前缀。如果你遵守前文所说的布尔字段的命名标准,那么你只需将字段名赋给它即可。例:isPersistent(), isString(),isCharacter()
l         类
采用完整的英文描述符,所有单词的第一个字母大写。例: Customer, SavingsAccount
l         构造函数
使用类名 Customer(), SavingsAccount()
l          析构函数
Java 没有析构函数,但一个对象在垃圾收集时,调用成员函数 finalize() 。 finalize()
l         异常
通常采用字母 e 表示异常。
l         静态常量字段(常量)
全部采用大写字母,单词之间用下划线分隔。
例:public static final String KEY_MEMBER = "member";
l         获取成员函数
被访问字段名的前面加上前缀 get。 例:getFirstName(), getLastName(),getWarpSpeed()
l         接口
采用完整的英文描述符说明接口封装,所有单词的第一个字母大写。习惯上,名字后面加上后缀 able, ible 或者 er,但这不是必需的。例:Runnable, Contactable, Prompter, Singleton
l         局部变量
采用完整的英文描述符,第一个字母小写,但不要隐藏已有字段。例如,如果有一个字段叫 firstName,不要让一个局部变量叫 firstName。 例:grandTotal, customer, newAccount
l         循环计数器
通常采用字母 i, j, k 或者 counter 都可以接受。例: i, j, k, counter
l         使用存取函数获得和修改所有字段
l         对常量直接获取
l         对于集合,加入成员函数来插入和删除项
l         一旦可能,将存取函数置为被保护类型,不是公共类型
l         字段一般定义为私有类型
l         不要直接访问字段,应使用存取成员函数
l         一定要初始化静态字段
l         按以下顺序声明一个类的字段和成员函数:
1)        构造函数
2)        finalize()
3)        私有字段
4)        公共成员函数
5)        被保护成员函数
6)        私有成员函数
l         不要隐藏名字(重名)
l         一行代码只声明一个局部变量
l         用一个行内注释说明局部变量
l         在使用局部变量之前声明它
l         将局部变量用于一件事
l         给代码加上注释
l         给代码分段
l         使用空白,控制结构之前用一个空行,成员函数之前用两个空行
l         一个成员函数应能在 30 秒内让人理解
l         写短小单独的命令行
l         尽量限制成员函数的可见性
l         说明操作的顺序
4.3.6    异常处理
异常处理通常有两种异常:
(1)       Checked-Exception
这种异常指的是程序设计人员能够事先判断到的,属于程序设计过程的一部分。设计人员应该考虑到系统在什么情况下,应该进行什么样的判断,可能会出现什么样的异常。比如,在添加一个用户时,如果用户输入的用户名已经存在,应该抛出用户已存在的异常。
(2)       Unchecked-Exception
这种异常包括两部分,error和runtime exception。Error为系统之外的无法预料的错误,它是无法通过try-catch进行处理的。Runtime exception通常是由于bug引起的,它是可以通过try-catch进行处理的,但是通常更好的方法是将它暴露出来,以便测试人员查找bug,比如Nullpointer exception。
程序员要处理的是Checked-exception,在进行Checked-exception的设计时,首先要考虑到什么场景下会出现异常,根据场景对异常类设计类名。通常异常类的包路径为com.acca.[project].[module].business.exception,异常类的名称为[module]+[exception description]+Exception.java,例如在admin模块下出现的用户名已存在的异常类,可以定义为AdminUserHasExistedException.java。异常类需要继承公司J2EE框架中的CommonCheckedException类。
对于异常的处理原则为,尽量只在Manager层抛出异常,并在Action层捕捉异常。异常中的Message为定义在本模块的Resource文件中的相应错误信息的key值。Action层捕捉到异常后,根据异常中的message获取到相应的错误信息,将其显示在页面上。
使用javadoc格式作为文档注释格式:
/**
*     This is a doc comment类功能描述
*     @xxxx功能说明注释
*/
类 :
@auther开发者/修改者
@version版本号
方法:
@param参数
@return返回值
@exception异常
l         文档注释
在紧靠接口、类、成员函数和字段声明的前面注释它们。注释语句由 javadoc 处理,为一个类生成外部文档。
/** 客户:客户是我们将服务和产品卖给的人或机构。
@author S.W. Ambler
*/
l         C 语言风格
采用 C 语言风格的注释去掉不再使用但你仍想保留的代码。仍想保留是因为用户万一会改变想法,或者在调试过程中想让它暂时失效。
/* 这部分代码因为已被它之前的代码取代,由 B.Gustafsson, 于 1999 年 6 月 4 日注释掉。如果两年之后还未使用,将其删除。
. . . (源代码)
*/
l         单行
在成员函数内采用单行注释,来说明业务逻辑、代码段和暂时变量的声明。
// 遵照 Sarek 的规定,给所有
// 超过 $1000 的发货单
// 打 5% 的折扣。让利活动
// 动于 1995年 2 月开始
下表概括了所写 Java 代码中的每一部分哪些需要注释说明。
项目 注释哪些部分
l         实参
1)        参数
2)        参数类型
3)        参数用来做什么
4)        任何约束或前提条件
l         字段
1)        字段/属性
2)        字段描述
3)        注释所有使用的不变量
l         类
1)        类的目的
2)        已知的问题
3)        类的开发/维护历史
4)        注释出采用的常量
l         接口
1)        目的
2)        它应如何被使用以及如何不被使用
l         局部变量
1)        用处/目的
l         成员函数注释
1)        成员函数做什么以及它为什么做这个
2)        哪些参数必须传递给一个成员函数
3)        成员函数返回什么
4)        已知的问题
5)        任何由某个成员函数抛出的异常
6)        成员函数是如何改变对象的
7)        包含任何修改代码的历史
8)        如何在适当情况下调用成员函数的例子
9)        适用的前提条件和 后置条件
l         成员函数内部注释
1)        控制结构
2)        代码做了些什么以及为什么这样做
3)        局部变量
4)        难或复杂的代码
5)        处理顺序
文件样式
所有的 Java(*.java) 文件都必须遵守如下的样式规则
所有java文件注释尽量用英文,请不要用中文
版权信息必须在 java 文件的开头,格式如下:
/**
* Title:
* Description:
* Copyright:  Copyright (c)
* Company:    ACCA
* @author
* @version    1.0
*/
其他不需要出现在 javadoc 的信息也可以包含在这里。
u       package 行要在 import 行之前,import 中标准的包名要在本地的包名之前,而且按照字母顺序排列。
u        如果 import 行中包含了同一个包中的不同子目录,尽量不用 * 来处理。
package hotlava.net.stats;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Observable;
import hotlava.util.Application;
这里使用 InputStream and OutputStream来代替java.io.* 。
接下来的是类的注释,一般是用来解释类的。
/**
*

A class representing a set of packet and byte counters
* It is observable to allow it to be watched, but only
* reports changes when the current set is complete
*/
接下来是类定义,extends 与 implements 分行描述
public class CounterSet extends Observable
implements Cloneable
接下来是类的成员变量:
/**
* Packet counters
*/
public int[] packets;
public 的成员变量必须生成文档(JavaDoc),因而必须用如上方式注释。
protected、private和 package 定义的成员变量如果名字含义明确的话,可以没有注释。若要注释请用双斜杠(//)
例:// departCode
protected int departCode = -1;
接下来是类变量的存取的方法。它只是简单的用来将类的变量赋值获取值的话,可以简单的写在一行上。其它的方法不要写在一行上。
/**
* Get the counters
* @return an array containing the statistical data.  This array has been
* freshly allocated and can be modified by the caller.
*/
public int[] getPackets() { return copyArray(packets, offset); }
public int[] getBytes() { return copyArray(bytes, offset); }
public int[] getPackets() { return packets; }
public void setPackets(int[] packets) { this.packets = packets; }
接下来是构造函数,它应该用参数递增的方式写(比如:参数多的写在后面)。
public CounterSet(int size){
this.size = size;
}
如果这个类是可以被克隆的,那么下一步就是 clone 方法:
public Object clone() {
try {
CounterSet obj = (CounterSet)super.clone();
obj.packets = (int[])packets.clone();
obj.size = size;
return obj;
}catch(CloneNotSupportedException e) {
throw new InternalError(”Unexpected CloneNotSUpportedException: ” + e.getMessage());
}
}
l         接下来下面开始写类的方法:
l         要紧靠在每个方法的前面,主要应用有以下几个
l         @param该标记在当前方法的“prameter”一节中增添一个条目,具体的描述可以跨越多行,可使用HTML标记,要求所有的 @param 要连在一起。
l         @return 该标记在当前方法的一个“Returns”小节。具体的描述可以跨越多行,可使用HTML标记。
l         @throws 该标记在当前方法的“Throws”一节中增添一个条目,JAVADOC会自动建立一个超连接让用户理解所抛出的异常,具体的描述可以跨越多行,可使用HTML标记,要求所有的 @throws 要连在一起。
l         @see 该标记在“See also”小节中增加一个超链接使其可以转到JAVADOC文档的其他部分或转到一个外部文档。具体后面可以采用以下几种模式之一即可
(1)package.class#method XXXXXX            //此形式最常用,省略包名表示在同一包
(2)XXXXX
(3)”文字”
/**
* Set the packet counters
* (such as when restoring from a database)
* @param  r1  input vector store message 1
* @param  r2  input vector store message 2
* @param  r3  input vector store message 3
* @param  r4  input vector store message 4
* @return    null
* @throws   if parameteter1 is error throw IllegalArgumentException
* @see jp.co.softbrain.wes.sfa.admin.AdminMenuPage#print()
*/
protected final void setArray(int[] r1, int[] r2, int[] r3, int[] r4)
throws IllegalArgumentException {
//
// Ensure the arrays are of equal size
//
if (r1.length != r2.length || r1.length != r3.length || r1.length != r4.length)
throw new IllegalArgumentException(”Arrays must be of the same size”);
System.arraycopy(r1, 0, r3, 0, r1.length);
System.arraycopy(r2, 0, r4, 0, r1.length);
}
方法 (推荐)
无论如何,每一个类都应该定义 toString 方法:
public String toString() {
String retval = ”CounterSet: ”;
for (int i = 0; i < data.length(); i++) {
retval += data.bytes.toString();
retval += data.packets.toString();
}
return retval;
}
方法
如果main(String[]) 方法已经定义了, 那么它应该写在类的底部。
l         对涉及到流程分支较多或算法比较复杂的程序段,建议在此之前对流程或算法进行适当的解释
l          对某些关键性的程序行,建议在其前一行或行尾加以注释
/*Check if cookieDepart is available;
If the administration login is needed, we should set the adminstration group code;
*/
boolean bForceAdmin = false;
if(session != null) {
Boolean Bool = (Boolean)session.getValue("force_admin");
if(Bool != null )
bForceAdmin = Bool.booleanValue();
}
if(!bForceAdmin&&cookieDepart_.equals("")==false)
departCode_ = Integer.parseInt(cookieDepart_); //get department's Code
System.out.println(cookieDepart_);
int np = departVector_.size();
boolean bEnter = false;
// Useless cookie's interferance should be avoild;
for (int i=0; iDepart p = (Depart)departVector_.elementAt(i);
if (p.getCode() == departCode_) {
bEnter = true;
}
}
… …
… …
必须用 javadoc 来为类生成文档。不仅因为它是标准,这也是被各种 java 编译器都认可的方法。
缩进应该是每行4个空格。
页宽应该设置为80字符. 源代码一般不会超过这个宽度, 并导致无法完整显示, 但这一设置也可以灵活调整. 在任何情况下, 超长的语句应该在一个逗号或者一个操作符后折行. 一条语句折行后, 应该比原来的语句再缩进4个字符.

要求{}对排列整齐,最好上下一致,原则上要求便于阅读和配对
简单的可写成一行
例:if (i < 0) { i ++ };
一般情况可用以下两种格式
if (i < 0) {   //{与条件语句在同一行
i ++
};

if (i < 0)
{                   //{与条件语句分为两行
i ++
};
} 语句永远单独作为一行。
l         左括号和后一个字符之间不应该出现空格, 同样, 右括号和前一个字符之间也不应该出现空格. 下面的例子说明括号和空格的错误及正确使用:
CallProc( AParameter ); // 错误
CallProc(AParameter); // 正确
l         不要在语句中使用无意义的括号. 括号只应该为达到某种目的而出现在源代码中。下面的例子说明错误和正确的用法:
if ((I) = 42) { // 错误 - 括号毫无意义
if (I == 42) or (J == 42) then // 正确 - 的确需要括号
5. 框架相关代码规范
5.1 表现层规范
表现层主要用于完成与用户的交互。在J2EE程序开发中,程序员所需要做的表现层开发主要包括JSP页面的编写,以及相关的Action代码编写。如果系统采用Struts1的表现层框架,还需要涉及到ActionForm代码的编写以及相应的Struts配置文件和Struts Validation配置文件的编写。对于上述文件的编写,除了需要遵照代码总体规范外,还需要遵守如下规范:
l         表现层代码包结构
对于Action和ActionForm的Java代码存放的包结构,见4.2.2-包的命名。
对于页面展示代码(jsp,html等)以及表现层配置文件,需要遵照如下包结构存放:
包名
说明
WebContent/images
页面展示代码中所用到的所有图片文件
WebContent/scripts
页面展示代码中所用到的javascript文件
WebContent/styles
页面展示代码中所用到的css文件
WebContent/WEB-INF/jsp
系统中所有的JSP文件的根目录,并且在该目录中存放不属于任何具体功能模块的页面显示文件,例如,frame.jsp,login.jsp,webContent.jsp等
WebContent/WEB-INF/jsp/[module]
系统中各个模块中的JSP文件,这里的[module]应该一一对应于4.2.2中的[module]
WebContent/WEB-INF/tld
存放jsp页面所用到的taglib文件
WebContent/WEB-INF
存放所有Struts Validate 文件以及Struts Config 文件以及web.xml
l         表现层代码编码规范
除了遵循前面提到的代码总体规范外,表现层代码的编写还需要遵循一些特殊的规范。对于使用Struts1框架构建的表现层的编码规范,请参见文档《如何创建一个Struts应用》。
5.2 应用层规范
在表现层与应用层之间,ACCA J2EE平台使用manager作为接口,当响应前台用户提交的操作时,前台代码会调用相应的manager的方法。
应用层又可以细分为三层:manager层,service层,以及数据访问层。
Manager层和service层都是与业务相关的。区别在于,manager层关注的是一个具体的应用逻辑的整个流程,而在这个流程中,可能会访问数据库,这时候就会调用service层,service层负责向数据访问层提交对具体数据对象的访问,而这些数据对象代表什么业务含义,对于数据访问层来讲是透明的。Manager层与service层之间通过数据持久化对象来进行数据传递。
数据访问层又分为两个方面:一是DAO,用于向数据层派发数据处理请求;一是O-R映射,即将数据表对象化,通过面向对象的方式进行数据管理以及数据处理。
应用层代码的编写在遵循代码总体规范的同时,还需要遵循一些特殊的规范,这些规范大多数都与Spring的配置和Hibernate相关。
l         应用层代码包结构
对于应用层Java代码存放的包结构,见4.2.2-包的命名。
对于Hibernate的配置文件的存放路径,我们已经在代码总体规范中进行了阐述。
对于Spring的配置文件,需要遵照如下包结构存放:
包名
说明
WebContent/WEB-INF/
系统中所有的Spring配置文件
l         应用层代码编码规范
除了遵循前面提到的代码总体规范外,应用层代码的编写还需要遵循一些特殊的规范。这些特殊的规范包括:
(1)       Hibernate类型映射
程序员可能会使用hibernate工具来生成hibernate实体映射文件和hibernate实体类,也可能会手工编写。Hibernate实体映射文件中,需要指明数据表字段所对应的hibernate实体类中的属性的类型。对于数据表字段的类型和java类的属性的类型对应,请遵循如下表要求:
Hibernate映射类型
Java类型
标准SQL类型
大小
integer/int
java.lang.Integer
INTEGER
4字节
long
java.lang.Long
BIGINT
8字节
short
java.lang.Short
SMALLINT
2字节
byte
java.lang.Byte
TINYINT
1字节
float
java.lang.Float
FLOAT
4字节
double
java.lang.Double
DOUBLE
8字节
big_decimal
java.math.BigDecimal
NUMERIC
character
java.lang.String
CHAR(1)
定长字符
string
java.lang.String
VARCHAR
变长字符
boolean/ yes_no/true_false
java.lang.Boolean
BIT
布尔类型
date
java.util.Date
DATE
日期
timestamp
java.util.Date
TIMESTAMP
日期
calendar
java.util.Calendar
TIMESTAMP
日期
calendar_date
java.util.Calendar
DATE
日期
binary
byte[]
BLOB
BLOB
text
java.lang.String
TEXT
CLOB
serializable
实现java.io.Serializablej接口的任意Java类
BLOB
BLOB
clob
java.sql.Clob
CLOB
CLOB
blob
java.sql.Blob
BLOB
BLOB
class
java.lang.Class
VARCHAR
定长字符
locale
java.util.Locale
VARCHAR
定长字符
timezone
java.util.TimeZone
VARCHAR
定长字符
currency
java.util.Currency
VARCHAR
定长字符
(2)       Hibernate关联关系映射的编写规范
Hibernate的关联关系映射是Hibernate映射的难点。对于具体的关于Hibernate关联关系映射的说明请参见Hibernate的官方reference文档。在此我们主要对Hibernate的关联关系映射提出一些规范,希望程序员在编写代码时遵守:
·         尽量使用双向关联(Bidirectional associations),因为单向关联关系不便于查询,通常大型系统需要对几乎所有的关联关系进行双向查询。双向多对一关联(即One to many/ many to one)为最常见的关联关系,这也是标准的父子关联关系;
·         尽量少使用不常用的关联映射。一个好的设计很少可能会用到many-to-many映射关系。大多数情况下,many-to-many映射关系都可以用两个指向连接表类的one-to-many关联来替代。事实上,我们可能遇到的大部分的关联关系都是one-to-many和many-to-one的。
(3)       使用单一主键,不使用复合主键
(4)       注意hibernate inverse的使用,具体说明请参见组内资源文档《Hibernate Inverse》
(5)       在编写hibernate程序时,请遵循hibernate的优化策略,具体说明参见组内资源文档《Hibernate Performance Tuning》
(6)       Manager级代码中不可以出现hql或者sql语句,并且Manager级代码中只可以调用service级代码中的方法,而不能直接使用任何与hibernate框架相关的对象或方法(不包括实体对象(PO))。
(7)       前台代码与Manager级代码的数据交互通过ValueObject来进行,而Manager级代码与service级代码的数据交互通过实体对象(PO)来进行。ValueObject与PO的转换在Manager中实现。
(8)       Service级代码中可以出现hql或者sql语句。但是这些语句需要定义为String常量,命名规则参照4.2.7中静态常量字段的命名规则。并且这些hql或者sql尽量使用绑定变量(bind variables),即对于查询语句中的非常量,使用“?”来代替。不可以使用拼字符串的方式拼写hql或sql语句。
(9)       Service级代码中不要使用hibernate的方法,而应该调用公司框架中的HibernateDao中的方法。避免业务代码与底层框架耦合过紧。
5.3 Web应用关键配置文件的书写方法
(1)       Web.xml
Web应用部署在web应用服务器上,web应用服务器通过工程中WEB-INF目录下的web.xml来启动web应用。Web.xml中包含一些关键的节点,它们的编写方法依照这些节点在web.xml中出现的顺序如下所示:
·         根节点
Web.xml文件的根节点元素为,web-app元素及其属性的定义如下:
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
·         Display-name
Web application在GUI工具上的显示名称。该元素节点的定义如下:
TMS
·         Context-param
Context-param声明web应用的servlet的初始化参数,每个context-param节点可以设定一个参数。在普通的SSH(Struts+Spring+Hibernate)应用中,这里主要是要指明Spring的配置文件路径。


contextConfigLocation

/WEB-INF/applicationContext.xml,/WEB-INF/spring-context.xml,/WEB-INF/spring-context-action.xml,/WEB-INF/spring-context-course.xml,/WEB-INF/spring-context-course-action.xml
,/WEB-INF/spring-context-admin.xml,/WEB-INF/spring-context-admin-action.xml,/WEB-INF/spring-context-history.xml,/WEB-INF/spring-context-history-action.xml,/WEB-INF/spring-context-plan.xml,/WEB-INF/spring-context-plan-action.xml


·         Filter
过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。我们可能会定义到的filter包括servlet编码过滤器,以及hibernate single session过滤器。前者用于对前台输入的字符进行字符集转换,使其符合后台服务器的字符集要求。Hibernate SingleSession过滤器用来确保在每个前台request的生命周期内,从第一次hibernate为该request建立数据库session后,保持该session直到request操作结束返回到前台才释放,也就是我们所说的open-session-in-view模式。

encodingFilter

com.acca.common.web.filter.EncodingFilter


encoding
UTF-8




openSessionInViewFilter

org.springframework.orm.hibernate3.support.OpenSessionInViewFilter


singleSession
true


·         Filter-mapping
一旦命名了一个过滤器,就要利用filter-mapping元素把它与一个或多个符合特定url-pattern的servlet或jsp页面相关联。例如,在使用struts1的情况下(action的url结尾定义为.do),对于上述filter,其filter-mapping为:

encodingFilter
*.do


openSessionInViewFilter
*.do

·         Listener
Lister指定了对于该应用的事件监听程序。事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。我们通常会使用到Spring的ContextLoaderListener,来初始化spring的application context:



org.springframework.web.context.ContextLoaderListener


·         Servlet
定义应用中用到的servlet,对于不同的前台框架(例如struts1, struts2, jsf),servlet的定义内容可能会有不同,对于struts1应用的servlet定义如下:

action

org.apache.struts.action.ActionServlet


config

/WEB-INF/struts-config.xml


2

·         Servlet-mapping
指定对于上述定义的servlet,为它赋予特定的url模式:

action
*.do

·         Welcome-file-list
Welcome-file-list元素指示服务器在收到引用一个目录名而不是具体到文件名的url时,使用哪个文件,例如:

index.jsp

·         Jsp-config
Jsp-config元素主要包括taglib这个字元素,用于指定jsp用到的标签库。对于struts1应用,该元素的定义如下:


struts-bean.tld
/WEB-INF/tld/struts-bean.tld


struts-html.tld
/WEB-INF/tld/struts-html.tld


struts-logic.tld
/WEB-INF/tld/struts-logic.tld


struts-tiles.tld
/WEB-INF/tld/struts-tiles.tld


struts-nested.tld

/WEB-INF/tld/struts-nested.tld


(2)       ApplicationContext.xml
我们需要在applicationContext.xml中给出Spring支持的应用所必须的一些公用bean的定义,比如session管理,事务管理等。这些bean包括:
·         propertyConfigurer
这个bean用来指定spring的配置文件中所用到的classpath下定义的properties文件。例如在定义了接下来所示示例代码中的这个bean后,接下来的配置代码中,如果要用到这些properties中定义的资源信息,可以通过如下所示方式访问这些信息,例如${hibernate.dialect},hibernate.dialect为hibernate.properties中定义的资源信息的key值:
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">


classpath:hibernate.properties



·         sessionFactory
sessionFactory bean用于创建与数据库的连接,并且为用户请求生成数据库session。由于数据层框架采用了Hibernate,sessionFactory bean的定义如下例所示:
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">


classpath:hibernate.cfg.xml




${hibernate.dialect}

true
true
50
30



hibernateProperties中定义的hibernate属性会用来覆盖classpath下hibernate.properties中的对应属性。
·         transactionManager
transactionManage bean为事务管理的具体实现。由于数据层框架采用了Hibernate ,transactionManager的定义如下:
class="org.springframework.orm.hibernate3.HibernateTransactionManager">




·         transactionProxy
transactionProxy bean用于提供事务管理的AOP支持。通过它将事务管理的具体实现与业务代码的具体实现联系起来。它的定义如下:
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
lazy-init="true">






PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED



在上述配置代码中,transactionManager属性指定了应用中具体的做事务管理的bean。transactionAttributes是这段配置代码中最重要的部分。在上述prop中,key指定的是代理应该为符合何种命名模式的方法进行事务控制。而prop的值指定的是事务控制的传播方式,它可以有如下几种:
PROPAGATION_REQUIRED:
支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS:
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY:
支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW:
新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED:
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER:
以非事务方式执行,如果当前存在事务,则抛出异常。
·         hibernateDAO
公司j2ee框架实现的数据访问对象(DAO),所有的service代码只能调用hibernateDAO中定义的方法对数据库进行操作。hibernateDAO的定义如下:
class="com.acca.common.business.dao.impl.HibernateDaoImpl">




·         baseService
公司j2ee框架实现的所有service类的基类,所有的service  bean都需要继承这个bean,这个bean中注入了hibernateDao,因此在各个service类的代码中不用再定义hibernateDao属性,各个service bean中也不用再显示注入hibernateDao bean。baseService的定义如下:
class="com.acca.common.business.service.impl.BaseServiceImpl">




(3)       业务代码部分的Spring配置文件
对于业务代码部分的Spring配置文件的命名格式和存放地址在前文已经进行了阐述,Spring配置文件中可以根据需要定义任何类型的bean。这里主要介绍一下业务代码部分的Spring配置都需要配置哪些常用的bean。
·         Manager
在我们定义的SSH工程中,所有的manager实现都需要交由Spring管理,对于一个manager bean的定义如下例所示:








对于上述所示的userManager bean,class属性指向其具体的manager实现类。Property属性为该实现类的指定属性进行赋值,也就是Spring中常说的依赖注入。一般来说,对于manager bean中所有用到的service bean都需要进行依赖注入,而对于注入的service bean中,所有需要进行事务控制的service,property的值都需要指向该service的transaction proxy bean。
·         Service
在我们定义的SSH工程中,所有的Service实现都需要交由Spring管理,对于一个service  bean的定义如下例所示:






对于上述所示roleService bean,class指向其具体的service实现类。Parent指向baseService,表示该service是继承的baseService bean。(注:Service实现类必须继承com.acca.common.business.service.impl.BaseServiceImpl)
对于所有需要事务管理的Service bean,我们都必须为其定义transaction proxy bean,service的transaction proxy bean继承transactionProxy 。transaction proxy bean最重要的属性就是target属性,它指向该proxy bean所代理的service bean,以此实现对其代理的service bean进行事务控制。