林炳文Evankaka原创作品。
转载请注明出处http://blog.csdn.net/evankaka
摘要:在程序开发过程中。一些IDE的配置、经常使用代类的积累以及经常使用框架的使用。
能帮助我们迅速写好代码,高速定位错误。同一时候,又有利于我们高速构造和部署,以及进行兴许的迭代开发。
文件夹:
一、IDE配置篇
二、规范project篇
三、经常使用代码篇
四、经常使用框架篇
五、其它工具
一、IDE配置篇
平时开发由于是选用Eclipse,所以在配置上假设一開始就配置好的话,开发的过程中就能够省去非常多步骤。首先是IDE的选择,这里由于平时用得最多的是Eclipse,所以主要还是针对它来说。到官网上去下载IDE,假设不做JAVA EE开发,建议选择第二个,当然。假设做安卓开发,也能够直接去下一直带有安卓SDK的Eclipse.
1.1、代码自己主动提示
Eclipse代码里面的代码提示功能默认是关闭的。仅仅有输入“.”的时候才会提示功能,以下说一下怎样改动eclipse配置,开启代码自己主动提示功能 Eclipse -> Window -> Perferences->Java -> Editor -> Content Assist 以下有三个选项,找到第二个“Auto activation triggers for Java:”选项 在其后的文本框中会看到一个“.”存在。这表示:仅仅有输入“.”之后才会有代码提示和自己主动补全,我们要改动的地方就是这里。把该文本框中的“.”换掉。换成“abcdefghijklmnopqrstuvwxyz.”。这样。你在Eclipse里面写Java代码就能够做到按“abcdefghijklmnopqrstuvwxyz.”中的随意一个字符都会有代码提示。
这是下个自己主动提示的样例
1.2、XML自己主动提示
在ssh或ssm框架中,都要写非常多的XML配置代码。
假设能在写的时候。自己主动显示一些提示代码。那就能够非常高速的把代码写出来。
DTD 类型约束文件
1. Window->Preferences->XML->XML Catalog->User Specified Entries窗体中,选择Add 按纽
2.在Add XML Catalog Entry 对话框中选择或输入以下内容:
Location: F:/soft/programmingSoft/Framework/Ibatis/sql-map-config-2.dtd
Key Type: URI
KEY: http://ibatis.apache.org/dtd/sql-map-config-2.dtd
XSD 类型约束文件
1. Window->Preferences->XML->XML Catalog->User Specified Entries窗体中,选择Add 按纽
2.在Add XML Catalog Entry 对话框中选择或输入以下内容:
Location: F:/soft/programmingSoft/Framework/Spring/spring-framework-2.5.6.SEC01-with-dependencies/spring-framework-2.5.6.SEC01/dist/resources/spring-beans-2.5.xsd
Key Type: Schema Location
KEY: http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
1.3、凝视自己主动生成
1、Java代码自己主动凝视
在使用Eclipse 编写Java代码时,自己主动生成的凝视信息都是依照预先设置好的格式生成的。
打开Windows->Preferences->Java->Code Style->Code Templates,点击右边窗体中的Comments,能够看到有非常多选项。我们便可对此凝视信息模板进行编辑。
如我们希望在一个Java文件的开头设置作者信息、日期信息。
为类和方法做凝视标准
注:方法的凝视自己主动生成方式为:输入/** 然后按下enter就可以。
或者在你须要加入凝视的地方点击Sources->Ganarate Element Comment,或者使用快捷键 Alt+Shift+J ,则 eclipse 自己主动在该类前面加入凝视。
2、jsp 文件部分
eclipse-->windows-->preferences-->Web-->JSP Files-->Editer-->Templates-->New JSP File-->单击[edit]button
在文件首行,加入例如以下内容:
Java代码
<%--
创建时间:${date}${time}
创 建 人:daniel
相关说明:
JDK1.6.0_21 tomcat6.0.29 servlet2.5
--%>
<%--
创建时间:${date}${time}
创 建 人:daniel
相关说明:
JDK1.6.0_21 tomcat6.0.29 servlet2.5
--%>
这样再创建 .java 或 .jsp 文件时,eclipse 就会为我们自己主动将凝视写好。
你还能够通过“导出”、“导入”功能,把自己的模板导出来,方便在其它机器上使用。
1.4 皮肤选择
在开发过程中。是不是感到白色的一片看得非常不舒服,特别是晚上的时候,屏幕太亮了。对眼晴实在不好。所幸Eclipse有这方面的皮肤库。在Eclipse lua中有自带的一个皮肤库Dark,选择方法
Window—>Preferences—>General—>Apperance选择主题为Dark。确认
结果例如以下
很多其它的皮肤模板请到这里来下吧!
1.4、快捷操作键使用
快捷操作平时是我使用最多的,用键盘的速度肯定比用鼠标来得快。高手都是直接快捷键来定位各种问题。
以下是一些我自己比較经常使用的快捷键,有兴趣的人也能够自己去百度下。
1、Ctrl+Shift+t:打开类型
假设你不是有意磨洋工,还是忘记通过源代码树(source tree)打开的方式吧。用eclipse非常easy打开接口的实现类
2、Alt+左右方向键:返回与前进
我们经常会遇到看代码时Ctrl+左键,层层跟踪。然后迷失在代码中的情况,这时仅仅须要按“Alt+左方向键”就能够退回到上次阅读的位置,同理,按“Alt+右方向键”会前进到刚才退回的阅读位置。就像浏览器的前进和后退button一样。
3、Ctrl+Shift+o:自己主动导入包
4、Ctrl+Shift+r:打开资源
这可能是全部快捷键组合中最省时间的了。
这组快捷键能够让你打开你的工作区中不论什么一个文件,而你仅仅须要按下文件名称或mask名中的前几个字母。比方applic*.xml。美中不足的是这组快捷键并不是在全部视图下都能用。
5、Ctrl+Shift+s:自己主动加入方法
能够加入一此set/get的方法,或toString等方法
6、Ctrl+Shift+/加入凝视,也能够用Ctrl+Shift+取消凝视
7、Ctrl+o:高速outline
假设想要查看当前类的方法或某个特定方法,但又不想把代码拉上拉下,也不想使用查找功能的话。就用ctrl+o吧。
它能够列出当前类中的全部方法及属性,你仅仅需输入你想要查询的方法名,点击enter就能够直接跳转至你想去的位置。
8、ctrl+f:高速查找9. alt+shift+r:重命名(或者F2)
重命名属性及方法在几年前还是个非常麻烦的事。须要大量使用搜索及替换,以至于代码变得零零散散的。
今天的Java IDE提供源代码处理功能,Eclipse也是一样。
如今,变量和方法的重命名变得十分简单,你会习惯于在每次出现更好替代名称的时候都做一次重命名。要使 用这个功能,将鼠标移动至属性名或方法名上。按下alt+shift+r,输入新名称并点击回车。就此完毕。
假设你重命名的是类中的一个属性,你能够点击alt+shift+r两次。这会呼叫出源代码处理对话框,能够实现get及set方法的自己主动重命名。
10.、ctrl+.及ctrl+1:下一个错误及高速改动
ctrl+.将光标移动至当前文件里的下一个报错处或警告处。这组快捷键我一般与ctrl+1一并使用,即改动建议的快捷键。
新版Eclipse的改动建 议做的非常不错,能够帮你解决非常多问题,如方法中的缺失參数,throw/catch exception,未执行的方法等等
11、高速复制一行
将光标放到某一行。按住Ctrl+Alt+Down,即能够在以下高速复制一行。按住Ctrl+Alt+Up,即能够在上面高速复制一行。
5、代码质量工具
二、规范project篇
软件开发是一个集体协作的过程,程序猿之间的代码经常进行交换阅读,因此。Java源程序有一些约定俗成的命名规定,主要目的是为了提高Java程序的可读性以及管理上的方便性。
好的程序代码应首先易于阅读。其次才是效率高低的问题。
2.1、代码凝视风格
代码凝视原则
1. 凝视应该简单清晰,避免使用装饰性内容。也就是说,不要使用象广告横幅那样的凝视语句。
2. 代码凝视的目的是要使代码更易于被同一时候參与程序设计的开发人员以及其它后继开发人员理解。
3. 先写凝视。后写代码。
写代码凝视的最好方法是在写代码之前就写凝视。这使你在写代码之前能够想想代码的功能和执行。而且这样确保不会遗漏凝视。
(假设程序的逻辑略微复杂点的话,这样做非常有效)
4. 凝视信息不仅要包含代码的功能,还应给出原因。
比如,以下例 1 中的代码显示金额在 $1,000 以上(包含 $1,000)的定单可给予 5% 的折扣。
为什么要这样做呢?难道有一个商业法则规定大额定单能够得到折扣吗?这样的给大额定单的特殊是有时限的呢,还是一直都这样?最初的程序设计者是否仅仅是由于大方大度才这样做呢?除非它们在某个地方(或者是在源代码本身。或者是在一个外部文档里)被凝视出来。否则你不可能知道这些。
if (grandTotal >= 1000.00)
{
grandTotal = grandTotal * 0.95;
}
更加具体的内容请看我的还有一个博文这里:http://blog.csdn.net/evankaka/article/details/46538109
2.2、代码命名
命名整体原则
1. 名字含义要明白,做到见名知义,如: User,Role, UserManager
2. 尽量使用英文名字作为变量名,假设要使用中文,请写上备注.
如:var hbType = null;// hb是中文“货币”的首字母缩写.
3. 採用大写和小写混合形式命名。提高名字的可读性
正确:UserManager
错误: usermanager
4. 尽量少用缩写,但假设一定要使用,就要慎重地使用。
应该保留一个标准缩写的列表,而且在使用时保持一致。比如,想对单词“number”採用缩写,使用 num 这样的格式,而且仅仅使用这一种形式.注意:要维护缩写词汇列表.
5. 全部文件的名称都是大写字母开头,大写和小写混合, 如UserList.jsp
6. 全部文件夹的名称都是小写字母开头,大写和小写混合, 如userType
7. 变量名不能以下划线开头,如“_account”,”_userName”是不同意的,由于下划线开头的变量可能被OWK平台做为保留字占用.
8. 避免使用类似或者仅在大写和小写上有差别的名字
比如。不应同一时候使用变量名 persistentObject 和 persistentObjects。以及 anSqlDatabase 和 anSQLDatabase。
命名
包
包结构定义=${包单元}[.${包单元}]*
说明:
1:一个包是由一个或多个构造单元组成,各构造单元之间以点号”.”隔开
2:一个包单元由一个或多个词组成
3:包单元应该是名词
• 业务系统的包结构是com.cmb.zct.${业务系统名字}.${模块名}
• 包名全部小写,如:com.cmb.zct.tx.OA.common是不同意的.但有种情况下同意出现大写字母,就是当包单元是由多个词组成时.如: com.cmb.zct.tx.oa.userType.
类
• 使用全然的英文描写叙述符,全部单词的第一个字母要大写,而且单词中大写和小写混合。
• 类名是名词或名词词组.如 LogManager
• 工具类以Util结尾 . 如FileUtil,StrUtil
• 异常类以Exception结尾.如RootDirNotExistsException
• 抽象类名以Abstract开头 AbstractGenerator
• 工厂类以Factory结尾,如 ConnFactory
• 接口同类名。大写和小写混合..
方法
• 成员函数的命名应採用完整的英文描写叙述符。大写和小写混合使用:全部中间单词的第一个字母大写。成员函数名称的第一个单词经常採用一个有强烈动作色彩的动词。首个单词小写。如:getUserInfo, removeEquipment
參数变量
以 小写p开头
如
public void sendMessage(String pMessage){
...............
}
注意:javabean 的參数变量不带p。
常量名
採用完整的英文大写单词,在词与词之间用下划线连接。MAX_VALUE,DEFAULT_START_DATE
文件夹名
同包名。小写字母开头。假设有多个单词构成,则第2个以后的单词以大写字母开头。
如user, userType文件夹
文件名称
同类名命名规则。大写字母开头,大写和小写混合。
如:EquipmentList.jsp
模块相关文件命名约束。为了方便说明。${MODEL_NAME}代表实际模块的名称,那各文件的名字必须满足下表格式要求.
文件 格式 举例
业务组件接口 I${MODEL_NAME}Facade.java IUserFacade.java
服务组件接口 I${MODEL_NAME}Service.java IUserService.java
业务组件实现类 ${MODEL_NAME}FacadeImpl.java UserFacadeImpl.java
服务组件实现类 ${MODEL_NAME}ServiceImpl.java IUserServiceImpl.java
測试类 ${MODEL_NAME}ServiceTest.java UserServiceTest.java
更加具体的内容请看我的还有一个博文这里:http://blog.csdn.net/evankaka/article/details/46538109
2.3、数据库规范
命名规范
1、 库表名、字段名尽量不用缩写(英文单词太长可适当缩写,但要能让人看明白含义,同一英语单词的缩写需保持一致)
2、 表名、字段名的各单词间必须用下划线分隔开
如 表名:USER_INFO 字段名:USER_CODE, USER_NAME
3、 必须为每一个子系统定义独立的schema
代码编写规范
1、 对数据库表、存储过程的訪问必须显示加上schema名称(mysql也叫database);
2、 不同意使用select * from 编写查询语句。必须显示写查询字段列表;
3、 不同意跨子系统直接訪问库表,跨子系统必须通过服务接口进行调用;
4、 批量操作必须採用jdbc的batch方式提交。
5、 尽量使用JDK自带的API函数。不要自己写类似功能的函数。
6、 Public方法中,对外部传入的不可信任的參数。须要进行有效性校验;
2.4、性能规范
2.4.1 日志处理
1. 避免显式调用对象的toString方法
Object param1 = "param1"; // 显式调用toString // 当当前日志级别为 info时。虽然没有打印到文件里,可是在方法调用參数传递时。已经做了一次toString的方法。 LOGGER.debug("打印一个參数:{}.", param1.toString()); // 正确的方式: LOGGER.debug("打印一个參数:{}.", param1);2. 对类中日志工具对象logger应声明为static。
虽然一些logger对LogFactory工厂有一些优化。可是我们也必须防止代码没有必要的执行。
3. 避免在循环中打印大量的日志。
2.4.2 字符串处理
1. 对于常量字符串,不要通过new方式来创建;
2. 对于常量字符串之间的拼接。请使用“+”;对于字符串变量(不能在编译期间确定其具体值的字符串对象)之间的拼接,请使用StringBuilder/StringBuffer;
3. 在使用StringBuilder/StringBuffer进行字符串操作时,请尽量设定初始容量大小;也尽量避免通过String/CharSequence对象来构建StringBuffer对象(即:不要使用 new StringBuilder(String) 这个构造方法来创建StringBuilder对象);
4. 当查找字符串时,假设不须要支持正則表達式请使用indexOf(…)实现查找(特殊情况能够使用startsWith和endsWith)。当须要支持正則表達式时。假设须要频繁的进行查找匹配,请直接使用正則表達式工具类实现查找。
5. 尽量避免使用String的split方法。
除非是必须的。否则应该避免使用split。split由于支持正則表達式,所以效率比較低,假设是频繁的几十,几百万的调用将会耗费大量资源。假设确实 须要频繁的调用split,能够考虑使用apache的StringUtils.split(string,char),频繁split的能够缓存结果。
6.
2.4.3 对象创建、销毁处理
1. 在循环外定义变量。
2. 对局部变量不须要显式设置为null。
3. 尽量避免非常大的内存分配。
从数据库中读取的记录放到集合中时,要注意控制集合元素个数。
4.
2.4.4 数组、集合处理
1. 数组的复制使用System.arraycopy(…)方法;
2. 对于数组、集合的拷贝、查找、排序等操作,假设是一般应用。能够优先採用java.util.Arrays和java.util.Collections 中提供的工具方法;可是对于热点代码。最好是參考java API中的方法实现,自己开发特定的排序等方法,以降低暂时对象的创建;
3. 当须要在方法之间传递多个属性值时。从性能角度考虑,应优先採用结构体。而非ArrayList或Vector等集合类。
4. 在代码开发中,须要依据应用场景合理选择集合框架中的集合类,应用场景可按单线程和多线程来划分,也可按频繁插入、随机提取等具体操作场景来划分。
5. 定义集合对象时,请尽量设定初始容量大小;
6.
2.4.5 IO处理
1. 在IO操作中,必须定义finally代码段,并在该代码段中执行IO关闭操作。
2. 进行IO读写操作时,必须使用缓冲机制;
2.4.6 多线程处理
1. 避免太多的使用 synchronized keyword。
尽量减小Synchronized的范围。
2. 在线程池中执行的子线程,其run方法不能够往外抛出异常。
2.4.6 其它规则
1. 避免在循环中对变量进行反复计算
避免使用这类的语句:for(int i=0; i<list.size(); i++)
应该使用:int size=list.size(); for(int i=0; i<size; i++)
更加优化的是使用迭代的方式:for(Object o: list)
2. 异常仅仅能用于错误处理,不应该用来控制代码流程
当创建一个异常时,须要收集一个栈跟踪(stack track),这个栈跟踪用于描写叙述异常是在何处创建的。
构建这些栈跟踪时须要为执行时栈做一份快照,正是这一部分开销非常大。
当须要创建一个 Exception时,JVM不得不说:先别动。我想就您如今的样子存一份快照,所以暂时停止入栈和出栈操作。
栈跟踪不仅仅包含执行时栈中的一两个元素,而是包含这个栈中的每一个元素。
三、经常使用代码篇
2.1、日期处理类
日期处理主要完毕了一些格式方面的转换
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import org.apache.commons.lang3.time.DateUtils; import com.google.common.primitives.UnsignedBytes; import com.lz.cts.common.errorcode.CtsErrorCode; import com.lz.ctsframework.core.support.ServiceException; /** * * <b>类说明:</b>日期工具类 * * <p> * <b>具体描写叙述:</b> * * @author ***** * @since ***** */ public class CtsDateUtil { public final static String DATE_FROMAT = "yyyyMMdd"; public final static String TIME_FORMAT = "HHmmss"; /** * 两个日期是否在跨度之内 * * @param startDate * @param endDate * @param gapType * 跨度类型。如Calendar.YEAR,Calendar.MONTH,Calendar.DAY_OF_YEAR * @param maxGap * 最大跨度值 * @return */ public static boolean isWithInDateGap(Date startDate, Date endDate, int gapType, int maxGap) { if (startDate == null) { throw new IllegalArgumentException("The startDate must not be null"); } if (endDate == null) { throw new IllegalArgumentException("The endDate must not be null"); } if (gapType != Calendar.YEAR && gapType != Calendar.MONTH && gapType != Calendar.DAY_OF_YEAR) { throw new IllegalArgumentException( "The value of gapType is invalid"); } Calendar start = Calendar.getInstance(); start.setTime(startDate); start.add(gapType, maxGap); int compare = start.getTime().compareTo(endDate); return compare >= 0; } /** * 两个日期是否在跨度之内 * * @param startDate * @param endDate * @param gapType * 跨度类型,如Calendar.YEAR,Calendar.MONTH,Calendar.DAY_OF_YEAR * @param maxGap * 最大跨度值 * @return * @throws ParseException */ public static boolean isWithInDateGap(String startDate, String endDate, int gapType, int maxGap){ Date startDateTime = null; Date endDateTime = null; try{ startDateTime = DateUtils.parseDate(startDate, DATE_FROMAT); endDateTime = DateUtils.parseDate(endDate, DATE_FROMAT); }catch(ParseException e){ throw new ServiceException(*****,new String[]{"交易日期"}, "開始日期:" + startDate + ",结束日期:" + endDate); } return isWithInDateGap(startDateTime,endDateTime, gapType, maxGap); } /** * 两个日期是否在跨度之内 * * @param startDate * @param endDate * @param gapType * 跨度类型,如Calendar.YEAR,Calendar.MONTH,Calendar.DAY_OF_YEAR * @param maxGap * 最大跨度值 * @return * @throws ParseException */ public static boolean isWithInDateGap(int startDate, int endDate, int gapType, int maxGap) throws ParseException { return isWithInDateGap( DateUtils.parseDate(String.valueOf(startDate), DATE_FROMAT), DateUtils.parseDate(String.valueOf(endDate), DATE_FROMAT), gapType, maxGap); } /** * <b>说明:</b> 获取系统当前日期 * * @param * @return * @ * @author **** * @since 2014年5月22日 */ public static int getCurIntPcDate() { return Integer.parseInt(getCurPcDate()); } /** * <b>说明:</b> 获取系统当前日期 * * @param * @return * @ * @author **** * @since **** */ public static String getCurPcDate() { java.util.Date currentDate = new java.util.Date(); SimpleDateFormat formatdate = new SimpleDateFormat(DATE_FROMAT); return formatdate.format(currentDate); } /*** * <b>说明:</b> 获取指定格式的系统当前日期 * @param * @return * @ * @author **** * @since **** */ public static String getCurPcDate(String strFormat) { java.util.Date currentDate = new java.util.Date(); SimpleDateFormat formatdate = new SimpleDateFormat(strFormat); return formatdate.format(currentDate); } /*** * <b>说明:</b> 获取当时系统日期时间【YYYYMMDDHHmmss】 * @param * @return * @throws ServiceException * @author yanfy * @since 2014年6月5日 */ public static String getCurPcDateTime() { java.util.Date currentDate = new java.util.Date(); SimpleDateFormat formatdate = new SimpleDateFormat(DATE_FROMAT+TIME_FORMAT); return formatdate.format(currentDate); } /** * <b>说明:</b> 获取当时系统日期时间【YYYYMMDDHHmmss】 * @param * @return * @author **** * @since 2014年6月5日 */ public static Long getIntCurPcDateTime() { return Long.valueOf(getCurPcDateTime()); } /** * <b>说明:</b> 获取系统当前时间 * * @param * @return 当前时间并格式化成“HHmmss”,如“123124” * @ * @author **** * @since **** */ public static String getCurPcTime() { java.util.Date currentDate = new java.util.Date(); SimpleDateFormat formatdate = new SimpleDateFormat(TIME_FORMAT); return formatdate.format(currentDate); } /** * <b>说明: </b>验证传入数值型日期[YYYYMMDD]是否合法 * * @param * @return * @ * @author **** * @return * @since ***** */ public static boolean checkDateFormat(int intDate) { return checkDateFormat(String.valueOf(intDate)); } /** * <b>说明: </b>验证传入字符型日期[YYYYMMDD]是否合法 * * @param * @return * @ * @author **** * @since **** */ public static boolean checkDateFormat(String strDate) { return checkDateFormat(strDate, DATE_FROMAT); } /** * <b>说明: </b>验证传入字符型日期是否合法 * * @param * @return * @ * @author *** * @since **** */ public static boolean checkDateFormat(int intDate, String strFormat) { return checkDateFormat(String.valueOf(intDate), DATE_FROMAT); } /** * <b>说明: </b>验证传入字符型日期是否合法 * * @param * @return * @ * @author **** * @since *** */ public static boolean checkDateFormat(String strDate, String strFormat) { try { DateUtils.parseDateStrictly(strDate, strFormat); return true; } catch (ParseException e) { return false; } } /** * <b>说明: </b>验证传入数值型时间[HH24MMSS]是否合法 * * @param * @return * @ * @author **** * @return * @since **** */ public static boolean checkTimeFormat(int intDate) { String strDate = String.valueOf(intDate); if(strDate.length() <6) strDate = CommUtil.LeftFill(strDate, '0', 6); System.out.println("curTime:"+strDate); return checkTimeFormat(strDate); } /** * <b>说明: </b>验证传入字符型时间[HH24MMSS]是否合法 * * @param * @return * @ * @author **** * @since **** */ public static boolean checkTimeFormat(String strDate) { return checkTimeFormat(strDate, TIME_FORMAT); } /** * <b>说明: </b>验证传入字符型时间是否合法 * * @param * @return * @ * @author **** * @since **** */ public static boolean checkTimeFormat(int intDate, String strFormat) { return checkTimeFormat(String.valueOf(intDate), DATE_FROMAT); } /** * <b>说明: </b>验证传入字符型时间是否合法 * * @param * @return * @ * @author **** * @since *** */ public static boolean checkTimeFormat(String strDate, String strFormat){ try { DateUtils.parseDateStrictly(strDate, strFormat); return true; } catch (ParseException e) { return false; } } /** * <b>说明: </b>日期转换 * @param strDate * @return */ public static Date parseDate(String strDate){ return parseDate(strDate, DATE_FROMAT); } /** * <b>说明: </b>日期转换 * @param strDate * @param strFormat * @return */ public static Date parseDate(String strDate,String strFormat){ try { return DateUtils.parseDateStrictly(strDate, strFormat); } catch (ParseException e) { throw new ServiceException(CtsErrorCode.ERROR_FORMAT,new String[]{"交易日期"}, "日期:" + strDate); } } /** * <b>说明: </b>日期转换 * @param intDate * @param strFormat * @return */ public static Date parseDate(int intDate,String strFormat){ return parseDate(String.valueOf(intDate), strFormat); } /** * <b>说明: </b>日期转换 * @param intDate * @return */ public static Date parseDate(int intDate){ return parseDate(String.valueOf(intDate)); } /** * 日期转换成字符串 * @param date * @param dateFormat * @return */ public static String date2String(Date date,String dateFormat) { SimpleDateFormat formatdate = new SimpleDateFormat(dateFormat); return formatdate.format(date); } /** * 日期转换成字符串 * @param date * @param dateFormat * @return 格式为YYYYMMDD */ public static String date2String(Date date) { return date2String(date,DATE_FROMAT); } /** * 日期转换成整数 * @param date * @param dateFormat * @return 格式为YYYYMMDD */ public static int date2Int(Date date) { String str = date2String(date,DATE_FROMAT); return Integer.parseInt(str); } /*** * <b>说明:</b> * @param * @return * @throws ServiceException * @author **** * @since *** */ public static String getCurrLastDay() { return getCurrAfterDay(1); } /*** * <b>说明:</b> * @param * @return * @throws ServiceException * @author **** * @since **** */ public static String getCurrAfterDay(int days) { Calendar theCa = Calendar.getInstance(); theCa.setTime(new Date()); theCa.add(theCa.DATE, -1*days); Date date = theCa.getTime(); SimpleDateFormat formatdate = new SimpleDateFormat(DATE_FROMAT); return formatdate.format(date); } /** * 获取交易日期之前的相隔天数的日期 * @param transDate 交易日期 * @param days 天数 * @return * @author **** * @since *** */ public static Integer getTransDateBeforeDay(Integer transDate,int days){ Calendar theCa = Calendar.getInstance(); theCa.setTime(parseDate(transDate)); theCa.add(Calendar.DATE, -1*days); Date date = theCa.getTime(); SimpleDateFormat formatdate = new SimpleDateFormat(DATE_FROMAT); return Integer.valueOf(formatdate.format(date)); } /** * 获取指定日期之后的相隔n年的日期 * @param transDate * @param years * @return * @return Integer */ public static Integer getDateAfterYear(Integer transDate, int years) { Calendar theCa = Calendar.getInstance(); theCa.setTime(parseDate(transDate)); theCa.add(Calendar.YEAR, years); Date date = theCa.getTime(); SimpleDateFormat formatdate = new SimpleDateFormat(DATE_FROMAT); return Integer.valueOf(formatdate.format(date)); } /** * 获取交易日期之后的相隔天数的日期 * @param transDate 交易日期 * @param days 天数 * @return * @author **** * @since **** */ public static Integer getTransDateAfterDay(Integer transDate,int days){ Calendar theCa = Calendar.getInstance(); theCa.setTime(parseDate(transDate)); theCa.add(Calendar.DATE, 1*days); Date date = theCa.getTime(); SimpleDateFormat formatdate = new SimpleDateFormat(DATE_FROMAT); return Integer.valueOf(formatdate.format(date)); } /** * 计算两个日期相差的天数 * @param beginDate 【YYYYMMDD】 * @param endDate 【YYYYMMDD】 * @return Integer * @author **** * @since **** */ public static Integer diffDate(Integer beginDate,Integer endDate){ Calendar theCa1= Calendar.getInstance(); Calendar theCa2= Calendar.getInstance(); theCa1.setTime(parseDate(beginDate)); theCa2.setTime(parseDate(endDate)); long between_days=(theCa2.getTimeInMillis()-theCa1.getTimeInMillis())/(1000*3600*24); return Integer.parseInt(String.valueOf(between_days)); } }
2.2、字符串处理类
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.MessageDigest; /** * MD5加密工具类 */ public class MD5EncoderUtil { private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; private static String algorithm = "MD5"; public static String encode(String salt, String rawPass) { return encode(rawPass.toLowerCase() + salt); } public static String encode(String rawPass) { String result = null; try { MessageDigest md5 = MessageDigest.getInstance(algorithm); // 加密后的字符串 result = byteArrayToHexString(md5.digest(rawPass.getBytes("utf-8"))); } catch (Exception ex) { ex.printStackTrace(); } return result; } public static String getFileMd5(File file) { FileInputStream fileInputStream = null; try { MessageDigest md5 = MessageDigest.getInstance(algorithm); fileInputStream = new FileInputStream(file); byte[] buffer = new byte[8192]; int length; while ((length = fileInputStream.read(buffer)) != -1) { md5.update(buffer, 0, length); } return byteArrayToHexString(md5.digest()); } catch (Exception e) { e.printStackTrace(); return null; } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static boolean isPasswordValid(String encPass, String loginName, String rawPass) { String pass1 = encPass; String pass2 = encode(loginName, rawPass); return pass1.toUpperCase().equals(pass2.toUpperCase()); } /* * 转换字节数组为16进制字串 */ private static String byteArrayToHexString(byte[] b) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) { resultSb.append(byteToHexString(b[i])); } return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) n = 256 + n; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } }
2.3、文件处理类
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.RandomAccessFile; import java.io.Reader; import java.io.Writer; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * <b>类说明:文件操作工具类</b> * * <p> * <b>具体描写叙述:</b> * * @author ***** * @since ***** */ public class FileOperateAssistUtil { // 日志记录 private static Logger logger = LoggerFactory.getLogger(FileOperateAssistUtil.class); /** * * <b>方法说明:</b> 创建文件文件夹,若路径存在,就不生成 * * <p> * <b>具体描写叙述:</b> * * @param * @return * @author ***** * @since ***** */ public static void createDocDir(String dirName) { File file = new File(dirName); if (!file.exists()) { file.mkdirs(); } } /** * * <b>方法说明:</b> 创建文件文件夹 * * <p> * <b>具体描写叙述:</b> * * @param * @return * @author ***** * @since ***** */ public static void isExistsMkDir(String dirName){ File file = new File(dirName); if (!file.exists()) { file.mkdirs(); } } /** * <b>方法说明:</b> 本地,在指定路径生成文件。若文件存在,则删除后重建。* * @param dirName * 本地路径名, * @param file * 文件, * @return List<Object> * @throws ServiceException * @author ***** * @since ***** */ public static void creatFileByName(File file){ try { if (file.exists()) { file.delete(); logger.info("发现同名文件:{},先执行删除。再新建。", file.getAbsolutePath()); } file.createNewFile(); logger.info("创建文件为:{}", file.getAbsolutePath()); } catch (IOException e) { logger.error("创建{}文件失败", file.getAbsolutePath(), e); } } /** * * <b>说明:</b> * <b>具体描写叙述:创建新文件,若文件存在则删除再创建。若不存在则直接创建</b> * @param * @returnType File * @since ***** * @author ***** */ public static File newFile(String fileName) { File file = new File(fileName); creatFileByName(file); return file; } /** * * <b>说明:</b> * <b>具体描写叙述:关闭写入流</b> * @param * @returnType void * @since ***** * @author ***** */ public static void closeWriter(Writer writer) { if (writer != null) { try { writer.close(); } catch (IOException e) { // throw new ServiceException(BatchErrorCode.FILE_CLOSE_EXCEPTION, e); logger.error("Close Writer cause Exception:", e); } } } /** * * <b>说明:</b> * <b>具体描写叙述:关闭写入流</b> * @param * @returnType void * @since ***** * @author ***** */ public static void closeReader(Reader reader) { if (reader != null) { try { reader.close(); } catch (IOException e) { logger.error("Close reader cause Exception:", e); } } } /** * * <b>说明:</b> * <b>具体描写叙述:关闭随机读写流</b> * @param * @returnType void * @since ***** * @author ***** */ public static void closeRandomAccessFile(RandomAccessFile raf){ if(raf != null){ try { raf.close(); }catch (IOException e) { throw new ServiceException(******,e, new String[]{"批量"}); } } } public static String getBatchNo(String transDate, Long i) { return transDate + getSerialNo(i); } public static String getFileBatchNo(String date) { if(StringUtils.isBlank(date)){ return CtsDateUtil.getCurPcDate(); } return date; } public static String getSerialNo(Long i) { return CommUtil.LeftFill(String.valueOf(i), '0', 3); } public static String getSerialNo(int i) { return CommUtil.LeftFill(String.valueOf(i), '0', 3); } /** * * <b>方法说明:</b> 创建控制文件 * * <p> * <b>具体描写叙述:</b> * * @param * @return * @author ***** * @since***** */ public static void createControlFile(File dataFile, Long count) { String controlFileName = dataFile.getAbsolutePath().replace(".DAT", ".CTL"); File controlFile = null; BufferedWriter bw = null; try { controlFile = new File(controlFileName); if (controlFile.exists()) { controlFile.delete(); controlFile.createNewFile(); } // 获取数据文件MD5 String dataFileMd5 = MD5EncoderUtil.getFileMd5(dataFile); StringBuilder controlFileContext = new StringBuilder().append(dataFile.getName()).append(" ") .append(dataFile.length()).append(" ").append(count.toString()).append(" ") .append(dataFileMd5 == null ?
"" : dataFileMd5); // 将MD5写入控制文件 bw = new BufferedWriter(new FileWriter(controlFile, true)); bw.write(controlFileContext.toString()); bw.flush(); } catch (Exception e) { throw new ServiceException(*****, e, new String[]{"控制文件"}, "创建控制文件时发生异常"); } finally { if (bw != null) { try { bw.close(); } catch (IOException e) { throw new ServiceException(*****, e, new String[]{"控制文件"}, "创建控制文件时发生异常"); } } } } /** * * <b>方法说明:</b> 校验MD5 * * <p> * <b>具体描写叙述:</b> * * @param * @return * @author ***** * @since ***** */ public static boolean md5Valid(File dataFile) throws ServiceException { String controlFileName = dataFile.getAbsolutePath().replace(".DAT", ".CTL"); // 获取数据文件的MD5 String dataFileMd5 = MD5EncoderUtil.getFileMd5(dataFile); String controlFileMd5 = ""; BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(new File(controlFileName))); String tempString = reader.readLine(); // 获取控制文件里的MD5 if(StringUtils.isNotBlank(tempString)){ controlFileMd5 = tempString.substring(tempString.lastIndexOf(" ") + 1, tempString.length()); }else{ throw new ServiceException(CtsErrorCode.ERROR_VALIDATE_MD5, new String[]{"文件"}, "校验文件MD5时发生异常"); } } catch (Exception e) { logger.error("校验文件MD5时发生异常", e); throw new ServiceException(CtsErrorCode.ERROR_VALIDATE_MD5, e, new String[]{"文件"}, "校验文件MD5时发生异常"); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { throw new ServiceException(CtsErrorCode.ERROR_VALIDATE_MD5, e, new String[]{"文件"}, "校验文件MD5时发生异常"); } } } return dataFileMd5.toUpperCase().equals(controlFileMd5.toUpperCase()); } /** * <b>方法说明:</b> 将字符串拆解按特定标记解析,封装为String[] * * @param String * tempString 须要拆分的字符串 * @param String * tempString 拆分符号 * @param String * tempString 拆分符号出现次数 * @return List<Object> * @throws ServiceException * @author ***** * @since ***** */ public static String[] parseStringToStringArray(String tempString, String sign, int num) { List<Object> strlist = new ArrayList<Object>(); String[] strList = new String[num + 1]; try { int i; for (i = 0; i < num; i++) { String s1 = tempString.substring(0, tempString.indexOf(sign)).trim(); tempString = tempString.substring(tempString.indexOf(sign) + 1).trim(); strlist.add(s1); strList[i] = s1; if (i == num - 1) { strlist.add(tempString); strList[i + 1] = tempString; break; } } } catch (Exception e) { logger.error("解析还款清算文件失败", e); throw new ServiceException(CtsErrorCode.ERROR_PARSE_FILE, e, new String[]{"还款清算"}, "解析还款清算文件失败"); } return strList; } /** * * <b>方法说明:</b>格式化时间 * * <p> * <b>具体描写叙述:</b> * * @param * @return * @author ***** * @since ***** */ public static String foamatTime(String transTime) { return CommUtil.LeftFill(transTime, '0', 6); } /** * <b>方法说明:</b> 上传文件 * * @param transDate * 交易日期 * @param localPath * 本地路径 * @param regName * 文件名称前缀 * @param remotePath * 远程路径 * @return * @throws ServiceException * @author ***** * @since ***** */ public static Long uploadFiles(String transDate, String localPath, String regName, String remotePath) { SftpClient sftpClient = new SftpClient(); try { sftpClient.connect(); File[] fileList = listDataAndControlFile(localPath, regName + transDate); List<String> fileNameList = new ArrayList<String>(); Long count = 0L; for (File file : fileList) { count++; fileNameList.add(file.getAbsolutePath()); } if(count>0) sftpClient.uploadBatch(remotePath, fileNameList); return count; }finally { sftpClient.disConnect(); } } public static void uploadFile(String loaclpath, String fileName, String remotePath) { SftpClient sftpClient = new SftpClient(); try { File file = new File(loaclpath, fileName); sftpClient.upload(remotePath, file.getAbsolutePath()); }finally { sftpClient.disConnect(); } } public static void uploadFile(String loaclpath, List<String> fileName, String remotePath) { SftpClient sftpClient = new SftpClient(); try { List<String> fileNameList = new ArrayList<String>(); Long count = 0L; for (String item : fileName) { count++; fileNameList.add(loaclpath+"//"+item); } if(count>0) sftpClient.uploadBatch(remotePath, fileNameList); }finally { sftpClient.disConnect(); } } /*** * 依照指定格式分隔字符串 * @param tempString * @param splitChar * @return * @return String[] */ public static String[] splitString(String tempString,String splitChar) { String[] splits = (tempString.replace("||", "| | ") + (" ")).split(splitChar); for(int i=0;i<splits.length;i++){ if(null == splits[i]){ splits[i]=""; } } return splits; } public static String packProperty(String value) { if (value == null) { return ""; } return value.trim(); } public static String packProperty(Integer value) { if (value == null) { return ""; } return value.toString(); } public static String packProperty(BigDecimal value) { if (value == null) { return ""; } return value.toString(); } /** * * <b> 方法说明:</b><BR> * 获取本地文件夹下过滤后的数据文件列表 * * @param localPath 要查询的数据文件的路径 * @param namePrefix 要过滤出来的数据文件前缀 * @return File[] 文件列表 * @author ***** */ public static File[] listDataFile(String localPath, final String namePrefix) { FilenameFilter nameFilter = new FilenameFilter() { @Override public boolean accept(File dir, String fileName) { return fileName.startsWith(namePrefix) && (fileName.endsWith(".DAT")); } }; File[] fileList = new File(localPath).listFiles(nameFilter); return fileList == null ? new File[0] : fileList; } /** * * <b>方法说明:</b> 获取本地文件夹下过滤后的数据文件和控制文件列表 * * @param * @return * @author ***** * @since ***** */ public static File[] listDataAndControlFile(String localPath, String reg) { final String regName = reg; logger.debug("localPath:"+localPath+",reg:"+reg); FilenameFilter nameFilter = new FilenameFilter() { @Override public boolean accept(File dir, String fileName) { return fileName.indexOf(regName) >= 0 && (fileName.endsWith(".DAT") || fileName.endsWith(".CTL")); } }; File[] fileList = new File(localPath).listFiles(nameFilter); return fileList; } public static File[] deleteFilesFromDir(String localPath, String reg) { File[] oldFileList = FileOperateAssistUtil.listDataAndControlFile(localPath,reg); for (File file : oldFileList) { file.delete(); } return oldFileList; } public static String getBatchNoByFile(File file) { String fileName = file.getName(); String str = fileName.substring(fileName.lastIndexOf("_") + 1, fileName.lastIndexOf(".")); return str.length() <= 3 ? str : "001"; } }
2.4、DAO基类
package com.lz.ctsframework.core.support; import java.util.List; import org.apache.ibatis.annotations.Param; /** * * <b>类说明:</b>dao基类 * * <p> * <b>具体描写叙述:</b> * * @author ** * @since *** */ public interface IBaseDao<T,E,K> { int countByCriteria(E criteria); int deleteByCriteria(E criteria); int deleteByPrimaryKey(K key); int insert(T entity); int insertSelective(T entity); List<T> selectByCriteria(E criteria); T selectByPrimaryKey(K key); int updateByCriteriaSelective(@Param("record") T entity, @Param("example") E criteria); //int updateByCriteria(@Param("record") T entity, @Param("example") E criteria); int updateByPrimaryKeySelective(T entity); //int updateByPrimaryKey(T entity); }
2.5、异常抛出类
package com.lz.ctsframework.core.support; import java.text.MessageFormat; /** * * <b>类说明:</b>Service层统一抛出的异常 * * <p> * <b>具体描写叙述:</b> * * @author ***** * @since ***** */ public class ServiceException extends RuntimeException { private static final long serialVersionUID = 6514891174875747380L; /** 异常错误码 **/ private String code; /** 异常描写叙述 **/ private String msg; /** 扩展异常描写叙述(包含msg) **/ private String extMsg; /** * ServiceException构造方法,有format字符组 * @param errorCode 错误码 * @param param format字符组 * @param extMsg 扩展信息,给出具体的错误值信息等 */ public ServiceException(ErrorCode errorCode,String param[],String ... extMsg) { super(null==errorCode ? "" : errorCode.getCode()); init(errorCode, param,extMsg); } /** * ServiceException构造方法,有format字符组 * @param errCode * @param paramsList */ public ServiceException(ErrorCode errCode, Object... paramsList) { Object[] params = null; if ((paramsList != null) && (paramsList.length > 0) && ((paramsList[(paramsList.length - 1)] instanceof Throwable))) { Object[] newParam = new Object[paramsList.length - 1]; System.arraycopy(paramsList, 0, newParam, 0, newParam.length); params = newParam; super.initCause((Throwable)paramsList[(paramsList.length - 1)]); } else { params = paramsList; super.initCause(null); } this.code = null==errCode ?"" : errCode.getCode(); this.msg = null==errCode ? "" : MessageFormat.format(errCode.getMsg(),params); this.extMsg = this.msg; } private void init(ErrorCode errorCode, String param[], String... extMsg) { this.code = null==errorCode ? "" : errorCode.getCode(); this.msg = null==errorCode ? "" : MessageFormat.format(errorCode.getMsg(),param); StringBuilder builder = new StringBuilder(100); builder.append(this.msg); if(null != extMsg){ for(String ext : extMsg ){ builder.append("[").append(ext).append("]"); } } this.extMsg = builder.toString(); } /** * * @param code 错误码 * @param msg 描写叙述信息 */ public ServiceException(String code, String msg) { super(code+":"+msg); this.code = code; this.msg = msg; } /** * 带Exception的构造方法,传format字符数组 * @param errorCode 错误码基类 * @param e 异常 * @param extMsg 扩展信息,给出具体的错误值信息等 */ public ServiceException(ErrorCode errorCode, Throwable e,String param[] , String ...extMsg ) { super(null==errorCode ? "" : errorCode.getCode(), e); init(errorCode, param, extMsg); } /** * * @param code 错误码 * @param msg 描写叙述信息 * @param e 异常 */ /*public ServiceException(String code, String msg,Throwable e) { super(code+":"+msg, e); this.code = code; this.msg = msg; }*/ /** * * * 方法说明:异常错误码 * * @return */ public String getCode() { return code; } /** * * * 方法说明:异常描写叙述信息 * * @return */ public String getMsg() { return msg; } public String getExtMsg() { return extMsg; } @Override public String getMessage() { return super.getMessage() + ","+extMsg; } public static void main(String[] args) { } }
2.6 JSON处理类
import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; /** * * <b>类说明:</b>Jackson工具类 * * <p> * <b>具体描写叙述:</b> * * @author **** * @since *** */ public class JacksonUtil { private static final ObjectMapper MAPPER = new ObjectMapper(); static { MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } private static final JsonFactory JSONFACTORY = new JsonFactory(); /** * 转换Java Bean 为 json */ public static String beanToJson(Object o) throws JsonParseException { StringWriter sw = new StringWriter(); JsonGenerator jsonGenerator = null; try { jsonGenerator = JSONFACTORY.createJsonGenerator(sw); MAPPER.writeValue(jsonGenerator, o); return sw.toString(); } catch (Exception e) { throw new RuntimeException(e+"转换Java Bean 为 json错误"); } finally { if (jsonGenerator != null) { try { jsonGenerator.close(); } catch (Exception e) { throw new RuntimeException(e+"转换Java Bean 为 json错误"); } } } } /** * json 转 javabean * * @param json * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static Object jsonToBean(String json, Class clazz) throws JsonParseException { try { // MAPPER.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); return MAPPER.readValue(json, clazz); } catch (Exception e) { throw new RuntimeException(e+"json 转 javabean错误"); } } /** * 转换Java Bean 为 HashMap */ @SuppressWarnings("unchecked") public static Map<String, Object> beanToMap(Object o) throws JsonParseException { try { return MAPPER.readValue(beanToJson(o), HashMap.class); } catch (Exception e) { throw new RuntimeException(e+"转换Java Bean 为 HashMap错误"); } } /** * 转换Json String 为 HashMap */ @SuppressWarnings("unchecked") public static Map<String, Object> jsonToMap(String json, boolean collToString) throws JsonParseException { Map<String, Object> map = null; try { map = MAPPER.readValue(json, HashMap.class); } catch (IOException e) { throw new RuntimeException(e+"转换Java Bean 为 HashMap错误"); } if (collToString) { for (Map.Entry<String, Object> entry : map.entrySet()) { if (entry.getValue() instanceof Collection || entry.getValue() instanceof Map) { entry.setValue(beanToJson(entry.getValue())); } } } return map; } /** * List 转换成json * * @param list * @return */ public static String listToJson(List<Map<String, String>> list) throws JsonParseException { JsonGenerator jsonGenerator = null; StringWriter sw = new StringWriter(); try { jsonGenerator = JSONFACTORY.createJsonGenerator(sw); new ObjectMapper().writeValue(jsonGenerator, list); jsonGenerator.flush(); return sw.toString(); } catch (Exception e) { throw new RuntimeException(e+"List 转换成json错误"); } finally { if (jsonGenerator != null) { try { jsonGenerator.flush(); jsonGenerator.close(); } catch (Exception e) { throw new RuntimeException(e+"List 转换成json错误"); } } } } /** * json 转List * * @param json * @return */ @SuppressWarnings("unchecked") public static List<Map<String, String>> jsonToList(String json) throws JsonParseException { try { if (json != null && !"".equals(json.trim())) { JsonParser jsonParse = JSONFACTORY.createJsonParser(new StringReader(json)); return (List<Map<String, String>>) new ObjectMapper().readValue(jsonParse, ArrayList.class); } else { throw new RuntimeException("json 转List错误"); } } catch (Exception e) { throw new RuntimeException(e+"json 转List错误"); } } }
四、经常使用框架
4.1、日志打印-高速定位错
也许有人看到这里会觉得日志不重要,由于大家平时用得最多的预计就是System.out.prinln()之类的。这样的方法对于小程序是没问题。可是。对于一个完整的项目。有开发、有測试的。一方面。你假设开发过程中,每一个地方都要手动的输出这些语句,岂不是非常麻烦。特别是使用Mybatis或Hibernate之类的框架,你想看看程序跑的时候,调用的SQL语句。
没有日志就非常难做到。
还有一方面,项目假设部署在server之上,測试人员在进行測试时,就无法使用System.out.之类的语句来看输出了。这时。统一的把程序执行的日志输出到一个文件里去。然后通过一些linux的命令。就能够高速找到报错的信息是什么。
这里兴趣的同学能够看我写的:Log4j具体使用教程
一个典型的Log4j结构:
在小的项目中,能够日志的作用没那么明显。可是把日志和框架结合起来用就非经常见。比方和Spring/mybatis/SprinMVC/Tomcat等的结合,打印出来的日志能够例如以下,这里日志的格式能够自己来控制,以及日志输入的等级。以下是控制台的输出日志
以下是输出到外部的日志文件
4.2、Maven-jar的自己主动管理
Maven还没出现之前,每次新建一个Java或web项目,都得往编程路径里放非常多Jar包。
传统引入jar的方式是将其放入web-inf->lib文件夹里面,无形中增大了项目,而且jar不能统一进行管理。使用Maven的优点之中的一个就是通过配置POM.XML文件自己主动下载jar包,而且通过中心库统一进行管理、版本号的控制等。
一个典型的maven的web项目结构:
使用Maven的一些优点
1. Maven的库是由开源组织维护,不须要我们再花精力去管第三方库。即使自己维护,也比較方便。
2. Maven对jar包的版本号管理有工具上的支持,比方将Release版本号和Snapshot版本号区分开,有利于SCM管理。
3. Maven是标准。用过的人多,不须要额外培训。
4. Maven的plugin比較多,能够有很多其它功能,Maven现有体系比較开放,採用的技术相对照较通用和成熟。plugin的机制也能够便于我们扩展很多其它功能。
5. Maven的库下载是即用即下,不须要实现全部down下来。
Maven的插件也是自己主动升级,能够方便的我们扩展新功能。
6. 能够非常方便的与eclipse, IDEA这样的主流的IDE集成
7. 版本号管理功能,这里的版本号管理不是指第三方库的版本号管理,而是项目的版本号管理
8. 网站功能:它的出现让我们能够对项目的状态一目了然,能够自己主动的把项目的状态和各种报表以网站的形式公布到内部网或者外部网,能够随时随地查看项目状态。有非常多中报表能够选择。包含,doc生成。代码规范的检查,自己主动bug检查。单元測试报表,单元測试的代码覆盖率报表。
总之,Maven作为一个构建工具,不仅帮我们自己主动化构建,还能抽象构建过程,提供构建任务实现.他跨平台,对外提供一致的操作接口,这一切足以使他成为优秀的,流行的构建工具.
可是Maven不仅是构建工具,他还是一个依赖管理工具和项目信息管理工具.他还提供了中央仓库,能帮我们自己主动下载构件.
使用Maven还能享受一个额外的优点,即Maven对于项目文件夹结构、測试用例命名方式等内容都有既定的规则,仅仅要遵循了这些成熟的规则,用户在项目间切换的时候就免去了额外的学习成本,能够说是约定优于配置(Convention Over Configuration)。
Maven环境搭建
a)Apache Maven下载网站:http://maven.apache.org/download.html
b)maven的安装
把Maven解压到安装文件夹后。须要设置两个环境变量——PATH和M2_HOME。设置这两个环境变量,假设Maven安装文件夹是 c:Program Filesmaven-2.0.9,
打开-》计算机-》属性-》高级系统设置-》环镜变量
键入以下的命令:
下载下来之后,解压,找个路径放进去, 把bin的位置设在环境变量里,新建环境变量MAVEN_HOME
c)验证Maven安装
由于Maven依赖Java执行环境。因此使用Maven之前须要配置Java的执行环境。下载并安装JDK。配置JDK的环境变量JAVA_HOME,否则maven将无法使用
配置完毕后,在Windows命令提示符下,输入mvn -v測试一下,配置成功显示如图:
4.3、MyBatis自己主动代码生成
具体看我的还有一博文http://blog.csdn.net/evankaka/article/details/47023955
4.4、SVN使用
SVN是Subversion的简称。是一个开放源代码的版本号控制系统。相较于RCS、CVS,它採用了分支管理系统,它的设计目标就是代替CVS。
集中式管理的工作流程例如以下图:
集中式代码管理的核心是server。全部开发人员在開始新一天的工作之前必须从server获代替码,然后开发,最后解决冲突,提交。全部的版本号信息都放在server上。
假设脱离了server。开发人员基本上能够说是无法工作的。以下举例说明:
開始新一天的工作:
1、从server下载项目组最新代码。
2、进入自己的分支,进行工作。每隔一个小时向server自己的分支提交一次代码(非常多人都有这个习惯。由于有时候自己对代码改来改去,最后又想还原到前一个小时的版本号,或者看看前一个小时自己改动了哪些代码,就须要这样做了)。
3、下班时间快到了,把自己的分支合并到server主分支上。一天的工作完毕,并反映给server。
这就是经典的svn工作流程,从流程上看,有不少缺点。但也有优点。
安装
1、IDE中安装SVN插件
Eclipse中安装能够看,http://now51jq.blog.51cto.com/3474143/1571625
VS中能够安装VisualSVN,它的下载地址:https://www.visualsvn.com/。
安装过程:http://blog.csdn.net/lincyang/article/details/5658274(VS上还推荐安装小番茄助手。非常强大的一个代码提示插件)
2、TortoiseSVN
这是一个带界面的SVN软件。能够在windows上来使用。
有须要能够到http://tortoisesvn.net/来下载。
然后直接一路安装就可以。
五、其它辅助工具
1、NodePate++
能够用来打开各种文件。如java,xml、配置文件等等
2、DBVisualizer
DbVisualizer是一个全然基于JDBC的跨平台数据库管理工具,内置SQL语句编辑器(支持语法高亮),凡是具有JDBC数据库接口的数据库都能够管理,已经在Oracle, Sybase, DB2, Informix, MySQL, InstantDB, Cloudcape, HyperSonic ,Mimer SQL上通过測试
3、Fiddler
Fiddler是一个http协议调试代理工具,它能够记录并检查全部你的电脑和互联网之间的http通讯,设置断点。查看全部的“进出”Fiddler的数据(指cookie,html,js,css等文件。这些都能够让你胡乱改动的意思)。 Fiddler 要比其它的网络调试器要更加简单,由于它不仅仅暴露http通讯还提供了一个用户友好的格式。
4、SecureCRT
SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序。简单地说是Windows下登录UNIX或Linuxserver主机的软件。
5、其它Eclipse插件
编码标准:CheckStyle 插件URL:http://eclipse-cs.sourceforge.net/update/
代码反复:PMD的CPD 插件URL:http://pmd.sourceforge.net/eclipse/
代码覆盖率:Eclemma 插件URL:http://update.eclemma.org
依赖项分析:JDepend 插件URL:http://andrei.gmxhome.de/eclipse/
复杂度分析:Eclipse Metric 插件URL:http://metrics.sourceforge.net/update