林炳文Evankaka原创做品。css
转载请注明出处http://blog.csdn.net/evankaka
html
摘要:在程序开发过程当中。一些IDE的配置、常用代类的积累以及常用框架的使用。java
能帮助咱们迅速写好代码,高速定位错误。同一时候,又有利于咱们高速构造和部署,以及进行兴许的迭代开发。mysql
文件夹:linux
1、IDE配置篇git
2、规范project篇web
3、常用代码篇spring
4、常用框架篇sql
5、其它工具
数据库
平时开发因为是选用Eclipse,因此在配置上假设一開始就配置好的话,开发的过程当中就可以省去很是多步骤。首先是IDE的选择,这里因为平时用得最多的是Eclipse,因此主要仍是针对它来讲。到官网上去下载IDE,假设不作JAVA EE开发,建议选择第二个,固然。假设作安卓开发,也可以直接去下一直带有安卓SDK的Eclipse.
Eclipse代码里面的代码提示功能默认是关闭的。仅仅有输入“.”的时候才会提示功能,如下说一下怎样改动eclipse配置,开启代码本身主动提示功能 Eclipse -> Window -> Perferences->Java -> Editor -> Content Assist 如下有三个选项,找到第二个“Auto activation triggers for Java:”选项 在其后的文本框中会看到一个“.”存在。这表示:仅仅有输入“.”以后才会有代码提示和本身主动补全,咱们要改动的地方就是这里。把该文本框中的“.”换掉。换成“abcdefghijklmnopqrstuvwxyz.”。这样。你在Eclipse里面写Java代码就可以作到按“abcdefghijklmnopqrstuvwxyz.”中的随意一个字符都会有代码提示。
这是下个本身主动提示的样例
在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
一、Java代码本身主动凝视
在使用Eclipse 编写Java代码时,本身主动生成的凝视信息都是依照预先设置好的格式生成的。
打开Windows->Preferences->Java->Code Style->Code Templates,点击右边窗体中的Comments,可以看到有很是多选项。咱们即可对此凝视信息模板进行编辑。
如咱们但愿在一个Java文件的开头设置做者信息、日期信息。
为类和方法作凝视标准
注:方法的凝视本身主动生成方式为:输入/** 而后按下enter就能够。
或者在你需要加入凝视的地方点击Sources->Ganarate Element Comment,或者使用快捷键 Alt+Shift+J ,则 eclipse 本身主动在该类前面加入凝视。
二、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 就会为咱们本身主动将凝视写好。
你还可以经过“导出”、“导入”功能,把本身的模板导出来,方便在其它机器上使用。
在开发过程当中。是否是感到白色的一片看得很是不舒服,特别是晚上的时候,屏幕太亮了。对眼晴实在很差。所幸Eclipse有这方面的皮肤库。在Eclipse lua中有自带的一个皮肤库Dark,选择方法
Window—>Preferences—>General—>Apperance选择主题为Dark。确认
结果例如如下
不少其它的皮肤模板请到这里来下吧!
快捷操做平时是我使用最多的,用键盘的速度确定比用鼠标来得快。高手都是直接快捷键来定位各类问题。
如下是一些我本身比較常用的快捷键,有兴趣的人也可以本身去百度下。
一、Ctrl+Shift+t:打开类型
假设你不是有意磨洋工,仍是忘记经过源代码树(source tree)打开的方式吧。用eclipse很是easy打开接口的实现类
二、Alt+左右方向键:返回与前进
咱们常常会遇到看代码时Ctrl+左键,层层跟踪。而后迷失在代码中的状况,这时仅仅需要按“Alt+左方向键”就可以退回到上次阅读的位置,同理,按“Alt+右方向键”会前进到刚才退回的阅读位置。就像浏览器的前进和后退button同样。
三、Ctrl+Shift+o:本身主动导入包
四、Ctrl+Shift+r:打开资源
这多是所有快捷键组合中最省时间的了。
这组快捷键可以让你打开你的工做区中不论什么一个文件,而你仅仅需要按下文件名称或mask名中的前几个字母。比方applic*.xml。美中不足的是这组快捷键并非在所有视图下都能用。
五、Ctrl+Shift+s:本身主动加入方法
可以加入一此set/get的方法,或toString等方法
六、Ctrl+Shift+/加入凝视,也可以用Ctrl+Shift+\取消凝视
七、Ctrl+o:高速outline
假设想要查看当前类的方法或某个特定方法,但又不想把代码拉上拉下,也不想使用查找功能的话。就用ctrl+o吧。
它可以列出当前类中的所有方法及属性,你仅仅需输入你想要查询的方法名,点击enter就可以直接跳转至你想去的位置。
八、ctrl+f:高速查找今天的Java IDE提供源代码处理功能,Eclipse也是同样。
现在,变量和方法的重命名变得十分简单,你会习惯于在每次出现更好替代名称的时候都作一次重命名。要使 用这个功能,将鼠标移动至属性名或方法名上。按下alt+shift+r,输入新名称并点击回车。就此完毕。
假设你重命名的是类中的一个属性,你可以点击alt+shift+r两次。这会呼叫出源代码处理对话框,可以实现get及set方法的本身主动重命名。
10.、ctrl+.及ctrl+1:下一个错误及高速改动
ctrl+.将光标移动至当前文件里的下一个报错处或警告处。这组快捷键我通常与ctrl+1一并使用,即改动建议的快捷键。
新版Eclipse的改动建 议作的很是不错,可以帮你解决很是多问题,如方法中的缺失參数,throw/catch exception,未执行的方法等等
十一、高速复制一行
将光标放到某一行。按住Ctrl+Alt+Down,即可以在如下高速复制一行。按住Ctrl+Alt+Up,即可以在上面高速复制一行。
五、代码质量工具
软件开发是一个集体协做的过程,程序猿之间的代码常常进行交换阅读,所以。Java源程序有一些约定俗成的命名规定,主要目的是为了提升Java程序的可读性以及管理上的方便性。
好的程序代码应首先易于阅读。其次才是效率高低的问题。
代码凝视原则
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
命名总体原则
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
命名规范
一、 库表名、字段名尽可能不用缩写(英文单词太长可适当缩写,但要能让人看明白含义,同一英语单词的缩写需保持一致)
二、 表名、字段名的各单词间必须用下划线分隔开
如 表名:USER_INFO 字段名:USER_CODE, USER_NAME
三、 必须为每个子系统定义独立的schema
代码编写规范
一、 对数据库表、存储过程的訪问必须显示加上schema名称(mysql也叫database);
二、 不一样意使用select * from 编写查询语句。必须显示写查询字段列表;
三、 不一样意跨子系统直接訪问库表,跨子系统必须经过服务接口进行调用;
四、 批量操做必须採用jdbc的batch方式提交。
五、 尽可能使用JDK自带的API函数。不要本身写相似功能的函数。
六、 Public方法中,对外部传入的不可信任的參数。需要进行有效性校验;
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.
1. 在循环外定义变量。
2. 对局部变量不需要显式设置为null。
3. 尽可能避免很是大的内存分配。
从数据库中读取的记录放到集合中时,要注意控制集合元素个数。
4.
1. 数组的复制使用System.arraycopy(…)方法;
2. 对于数组、集合的拷贝、查找、排序等操做,假设是通常应用。可以优先採用java.util.Arrays和java.util.Collections 中提供的工具方法;但是对于热点代码。最好是參考java API中的方法实现,本身开发特定的排序等方法,以下降暂时对象的建立;
3. 当需要在方法之间传递多个属性值时。从性能角度考虑,应优先採用结构体。而非ArrayList或Vector等集合类。
4. 在代码开发中,需要依据应用场景合理选择集合框架中的集合类,应用场景可按单线程和多线程来划分,也可按频繁插入、随机提取等具体操做场景来划分。
5. 定义集合对象时,请尽可能设定初始容量大小;
6.
1. 在IO操做中,必须定义finally代码段,并在该代码段中执行IO关闭操做。
2. 进行IO读写操做时,必须使用缓冲机制;
2.4.6 多线程处理
1. 避免太多的使用 synchronized keyword。
尽可能减少Synchronized的范围。
2. 在线程池中执行的子线程,其run方法不可以往外抛出异常。
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不得不说:先别动。我想就您现在的样子存一份快照,因此暂时中止入栈和出栈操做。
栈跟踪不只仅包含执行时栈中的一两个元素,而是包含这个栈中的每个元素。
日期处理主要完毕了一些格式方面的转换
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)); } }
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]; } }
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("\t") .append(dataFile.length()).append("\t").append(count.toString()).append("\t") .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("\t") + 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"; } }
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.五、异常抛出类
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) { } }
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错误"); } } }
也许有人看到这里会以为日志不重要,因为你们平时用得最多的预计就是System.out.prinln()之类的。这样的方法对于小程序是没问题。但是。对于一个完整的项目。有开发、有測试的。一方面。你假设开发过程当中,每个地方都要手动的输出这些语句,岂不是很是麻烦。特别是使用Mybatis或Hibernate之类的框架,你想看看程序跑的时候,调用的SQL语句。
没有日志就很是难作到。
还有一方面,项目假设部署在server之上,測试人员在进行測试时,就没法使用System.out.之类的语句来看输出了。这时。统一的把程序执行的日志输出到一个文件里去。而后经过一些linux的命令。就可以高速找到报错的信息是什么。
这里兴趣的同窗可以看我写的:Log4j具体使用教程
一个典型的Log4j结构:
在小的项目中,可以日志的做用没那么明显。但是把日志和框架结合起来用就非常常见。比方和Spring/mybatis/SprinMVC/Tomcat等的结合,打印出来的日志可以例如如下,这里日志的格式可以本身来控制,以及日志输入的等级。如下是控制台的输出日志
如下是输出到外部的日志文件
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 Files\maven-2.0.9,
打开-》计算机-》属性-》高级系统设置-》环镜变量
键入如下的命令:
下载下来以后,解压,找个路径放进去, 把bin的位置设在环境变量里,新建环境变量MAVEN_HOME
c)验证Maven安装
因为Maven依赖Java执行环境。所以使用Maven以前需要配置Java的执行环境。下载并安装JDK。配置JDK的环境变量JAVA_HOME,不然maven将没法使用
配置完毕后,在Windows命令提示符下,输入mvn -v測试一下,配置成功显示如图:
具体看个人还有一博文http://blog.csdn.net/evankaka/article/details/47023955
SVN是Subversion的简称。是一个开放源代码的版本号控制系统。相较于RCS、CVS,它採用了分支管理系统,它的设计目标就是代替CVS。
集中式管理的工做流程例如如下图:
集中式代码管理的核心是server。所有开发人员在開始新一天的工做以前必须从server获代替码,而后开发,最后解决冲突,提交。所有的版本号信息都放在server上。
假设脱离了server。开发人员基本上可以说是没法工做的。如下举例说明:
開始新一天的工做:
一、从server下载项目组最新代码。
二、进入本身的分支,进行工做。每隔一个小时向server本身的分支提交一次代码(很是多人都有这个习惯。因为有时候本身对代码改来改去,最后又想还原到前一个小时的版本号,或者看看前一个小时本身改动了哪些代码,就需要这样作了)。
三、下班时间快到了,把本身的分支合并到server主分支上。一天的工做完毕,并反映给server。
这就是经典的svn工做流程,从流程上看,有很多缺点。但也有优势。
安装
一、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上还推荐安装小番茄助手。很是强大的一个代码提示插件)
二、TortoiseSVN
这是一个带界面的SVN软件。可以在windows上来使用。
有需要可以到http://tortoisesvn.net/来下载。
而后直接一路安装就能够。
一、NodePate++
可以用来打开各类文件。如java,xml、配置文件等等
二、DBVisualizer
DbVisualizer是一个全然基于JDBC的跨平台数据库管理工具,内置SQL语句编辑器(支持语法高亮),凡是具备JDBC数据库接口的数据库都可以管理,已经在Oracle, Sybase, DB2, Informix, MySQL, InstantDB, Cloudcape, HyperSonic ,Mimer SQL上经过測试
三、Fiddler
Fiddler是一个http协议调试代理工具,它可以记录并检查所有你的电脑和互联网之间的http通信,设置断点。查看所有的“进出”Fiddler的数据(指cookie,html,js,css等文件。这些都可以让你胡乱改动的意思)。 Fiddler 要比其它的网络调试器要更加简单,因为它不只仅暴露http通信还提供了一个用户友好的格式。
四、SecureCRT
SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序。简单地说是Windows下登陆UNIX或Linuxserver主机的软件。
五、其它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