1 系统架构
所谓系统架构是指,整合应用系统程序的结构。经常提到的系统结构有两种:三层架构与MVC。这两种结构既有区别,又有联系。但是这两种结构的使用,均是为了降低系统耦合度。
1.1 三层架构
三层架构是指:视图层View、服务层Service,和持久层Dao。它们分别完成不同的功能。
View层:用于接收用户提交请求的代码在这里编写。
Service层:系统的业务逻辑主要在这里完成。
Dao层:直接操作数据库的代码在这里编写。
1.2 MVC架构
MVC,即Model模型、View视图,以及Controller控制器。
View:视图,为用户提供使用界面,与用户直接进行交互。
Model:模型,处理用户提交请求,并计算出响应结果的模块。
Controller:控制器,用于将用户请求转发给相应的Model进行处理,并根据Model的计算结果向用户提供相应响应。
1.3 MVC与三层架构的关系
MVC架构和三层架构可以综合使用,如下图所示。
三层架构中,View层包含MVC架构中的Controller控制器和View视图;MVC架构中,Model模型包括三层架构中的Service层和Dao层。
1.4 SSH框架与三层架构之间的关系
SSH,即Struts2、Spring与Hibernate三个框架,它们在三层架构中所处的位置是不同的,即它们在三层架构中的功能各不相同,各司其职。
Struts2:作为View层的实现者,完成用户的请求接收功能。Struts2的Action作为整个应用的控制器,完成用户请求的转发及对用户的响应。
Hibernate:作为Dao层的实现者,完成对数据库的增、删、改、查功能。
Spring:以整个应用大管家的身份出现,整个应用中所有Bean的生命周期行为,均由Spring来管理,即整个应用中所有对象的创建、初始化、销毁,以及对象间关联关系的维护,均由Spring进行管理。
2 JUnit测试
JUnit是一个Java编程语言编写的单元测试框架,仅适合于纯粹的单元测试。
2.1 Jar包的下载
使用Junit进行测试,需要导入Jar包,Junit的官网为:http://junit.org
我使用的jar包为:junit-4.9.jar
2.2 测试类的创建
对于测试类的创建有一些习惯:
1、在项目中新建一个source folder,并命名为test,将所有测试类均定义在在这个项目中。
2、对于测试类所在包,一般是被测试类所在包的包名后再加上一个test子包。
3、对于测试类类名,一般是被测类类名后加上test。2.2.1 测试类的创建
直接创建Junit Test Case。此时,会自动导入其需要的jar包。
在创建过程中,勾选上setUp()和tearDown()方法。
示例代码如下:
package com.eason.dao.test;import static org.junit.Assert.*;import org.junit.After;import org.junit.Before;import org.junit.Test;public class StudentDaoImplTest { //测试方法执行之前执行,主要用于测试前的初始化,如连接数据库等。 @Before public void setUp() throws Exception { } //测试方法执行之后执行,主要用于资源释放,如关闭数据库连接等。 @After public void tearDown() throws Exception { } //对于测试方法的命名,一般是以小写test开头,该测试方法用于测试哪个方法,就将该方法名放于test之后,当然首字母大写。 @Test public void testInsertStudent() { System.out.println("testInsertStudent..."); }}
2.2.2 测试类中测试方法的运行
在测试方法的方法签名上右击,选择 Run As/JUnit Test。
运行结果看到绿条,则说明运行成功;看到红条,则说明运行出了问题。
3 Log4j
一个完整的软件,日志是必不可少的。程序从开发、测试、维护、运行等环节,都需要向控制台或者文件等位置输出大量信息。这些信息的输出,在很多时候是使用System.out.println()无法完成的。
日志信息根据用途与记录内容的不同,分为调试日志,运行日志,异常日志等。
用于日志记录的技术有很多,如jdk的logger技术,apache的log4j、log4j2技术等。
log4j的全称为Log for java,即:专门用于java语言的日志记录工具,其目前有两个版本:Log4j和Log4j2。
3.1 Log4j和Log4j2的下载
Log4j和Log4j2下载地址为:http://logging.apache.org/
3.2 日志级别
为了方便对于日志信息的输出显示,对日志内容进行了分级管理,日志级别由高到低,共分为6个级别:fatal(致命的)、error、warn、info、debug、trace(堆栈)。
那为什么要对日志进行分级呢?
无论是将日志输出到控制台,还是文件,其输出都会降低程序的运行效率。但由于调试、运行维护的需要,客户的要求等原因,需要进行必要的日志输出。这时就必须要在代码中加入日志输出语句。
这些输出语句若在程序运行时全部执行,则势必会降低运行效率。例如,使用System.out.println()将信息输出到控制台,则所有的该输出语句均将执行。会大大降低程序的执行效率。而要使其不输出,唯一的办法就是将这些输出语句逐个全部删除。这是个费时费力的过程。
将日志信息进行分级管理,便可方便地控制信息输出内容以及输出位置:哪些信息需要输出,哪些信息不需要输出,只需在一个日志输出控制文件中稍加修改即可。而代码中的输出语句不用做任何修改。
从这个角度来说,代码中的日志编写,其实就是写大量的输出语句。只不过,这些输出语句比较特殊,它们具有级别,在程序运行期间不一定被执行。它们的执行是由另一个控制文件控制的。
3.3 日志输出控制文件
log4j的日志输出控制文件,主要由三个部分构成:
1、日志信息的输出位置:控制日志信息将要输出的位置,是控制台还是文件等。
2、日志信息的输出格式:控制日志信息的显示格式,即以怎么样的字符串形式显示。
3、日志信息的输出级别:控制日志信息的显示内容,即显示哪些级别的日志信息。有了日志输出控制文件,代码中只要设置好日志信息内容以及级别即可,通过控制文件便可控制这些日志信息的输出。
4 Log4j技术
4.1 在程序中的日志实现步骤
若要在自己的程序中写入日志语句,则可以按照以下步骤进行:
1、导入Jar包:在项目中导入log4j需要的jar包。
2、放入日志输出控制文件:将属性文件log4j.properties直接放到项目的src下。##define an appender named console log4j.appender.console=org.apache.log4j.ConsoleAppender #The Target value is System.out or System.err log4j.appender.console.Target=System.err #set the layout type of the apperder log4j.appender.console.layout=org.apache.log4j.PatternLayout #set the layout format pattern log4j.appender.console.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n ##define an appender named file log4j.appender.file=org.apache.log4j.FileAppender #define the file path and name log4j.appender.file.File=d:/logfile.txt #set the layout type of the apperder log4j.appender.file.layout=org.apache.log4j.PatternLayout #set the layout format pattern log4j.appender.file.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n ##define an appender named rollfile log4j.appender.rollfile=org.apache.log4j.RollingFileAppender #define the file path and name log4j.appender.rollfile.File=d:/logrollfile.txt #set the log's size log4j.appender.rollfile.MaxFileSize=10KB #set the layout type of the apperder log4j.appender.rollfile.layout=org.apache.log4j.PatternLayout #set the layout format pattern log4j.appender.rollfile.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n ##define a logger #log4j.rootLogger=debug,console,file,rollfile log4j.rootLogger=INFO,console
3、代码中实现日志记录:在要输出日志的类中创建日志对象Logger,并通过Logger的方法在代码中加入日志输出语句。在Java代码中进行日志输出,需要用到Logger类的静态方法getLogger()。
注意,Logger为org.apache.log4j包中的类。
package com.eason.log4j.test;import org.apache.log4j.Logger;public class MyTest { public static void main(String[] args) { //创建日志记录对象Logger Logger logger = Logger.getLogger(MyTest.class); logger.fatal("fatal msg"); logger.error("error msg"); logger.warn("warn msg"); logger.info("info msg"); logger.debug("debug msg"); logger.trace("trace msg"); }}
将来这些日志输出语句,会根据log4j.properties文件中日志级别的设置进行输出。会输出到指定位置,其输出结果是:输出指定级别以及更高级别的信息。如指定Info级别,则会输出fatal、error、warn、info级别的信息。就本例而言,会执行以下三句,而不会执行debug()方法。
[FATAL][2018-01-01 10:23:33] com.eason.log4j.test.MyTest 9 fatal msg[ERROR][2018-01-01 10:23:33] com.eason.log4j.test.MyTest 10 error msg[WARN ][2018-01-01 10:23:33] com.eason.log4j.test.MyTest 11 warn msg[INFO ][2018-01-01 10:23:33] com.eason.log4j.test.MyTest 12 info msg
4.2 日志输出控制文件分析
日志属性文件log4j.properties是专门用于控制日志输出的,其主要进行三个方面控制:输出位置:控制日志将要输出的位置,是控制台还是文件等;输出布局:控制日志信息的显示形式;输出级别:控制要输出的日志级别。
日志属性文件由两个对象组成:日志附加器和根日志。
根日志:即为Java代码中的日志记录器,其主要由两个属性构成:日志输出级别和日志附加器。
日志附加器:则由日志输出位置定义,由其他很多属性进行修饰,如输出布局、文件位置、文件大小等。
1、定义日志附加器appender:
所谓日志附加器,就是为日志记录器附加上很多其他设置信息。附加器的本质是一个接口,其定义语法为:log4j.appender.appenderName = 输出位置。(appenderName为自定义名称)
输出位置为log4j指定的类型,是定义好的一些appender接口的实现类。查看log4j框架解压目录下的站点目录site的index.jsp中的JavaDoc,可看到log4j的API。
例如定义一个名称为console的控制台附加器:
##define an appender named consolelog4j.appender.console=org.apache.log4j.ConsoleAppender
常用的附加器实现类有四个,如下:
org.apache.log4j.ConsoleAppender:日志输出到控制台;org.apache.log4j.FileAppender:日志输出到文件。
org.apache.log4j.RollingFileAppender:当日志文件大小到达指定尺寸的时候将产生一个新的日志文件;org.apache.log4j.DailyRollingFileAppender:每天产生一个日志文件。
2、修饰日志附加器
所谓修饰日志附加器,就为定义好的附加器添加一些属性,以控制到指定位置的输出。不同的附加器,其修饰属性不同。
- 控制台附加器:##define an appender named consolelog4j.appender.console=org.apache.log4j.ConsoleAppender#The Target value is System.out or System.errlog4j.appender.console.Target=System.err#set the layout type of the apperderlog4j.appender.console.layout=org.apache.log4j.PatternLayout#set the layout format patternlog4j.appender.console.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n
Target:即控制输出到控制台的使用目标。其值为System.out或者System.err。它们的区别是:System.out是以黑色字体显示到控制台,而System.err则是以红色字体显示。
- 文件附加器:
##define an appender named filelog4j.appender.file=org.apache.log4j.FileAppender#define the file path and namelog4j.appender.file.File=d:/logfile.txt#set the layout type of the apperderlog4j.appender.file.layout=org.apache.log4j.PatternLayout#set the layout format patternlog4j.appender.file.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n
File:为日志要输出的文件位置以及文件名称。
- 滚动文件附加器
##define an appender named rollfile log4j.appender.rollfile=org.apache.log4j.RollingFileAppender #define the file path and name log4j.appender.rollfile.File=d:/logrollfile.txt #set the log's size log4j.appender.rollfile.MaxFileSize=10KB #set the layout type of the apperder log4j.appender.rollfile.layout=org.apache.log4j.PatternLayout #set the layout format pattern log4j.appender.rollfile.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n
MaxFileSize:用于指定日志文件的最大值,若文件超过指定值,将自动产生另一个日志文件。
- Log4j常用布局类型:
org.apache.log4j.HTMLLayout:网页布局,以HTML表格形式布局。
org.apache.log4j.SimpleLayout:简单布局,包含日志信息的级别和信息字符串。
org.apache.log4j.PatternLayout:匹配器布局,可以灵活地指定布局模式。其主要是通过设置Pattern的ConversionPattern属性值来控制具体输出格式的。ConversionPattern的值中有很多控制字符。
3、配置根Logger
配置rootLogger,以便于代码加载来控制日志的输出,其语法为:
log4j.rootLogger = [level], appenderName, ...
其中,level是日志记录的优先级,分为OFF,FATAL、ERROR、WARN、INFO、DEBUG、ALL。Log4j只使用四个级别,优先级从高到低分别是:ERROR、WARN、INFO、DEBUG。OFF为关闭日志功能。
低级别的可以显示高级别,但是高级别不能够显示低级别。所以,级别越高,将要显示的信息就越少。
5 log4j2技术
log4j2,是对log4j的升级,其在配置和使用上发生了较大变化。
5.1 在程序中的日志实现步骤
1、导入jar包:使用log4j2,需要导入其jar包,log4j框架解压后的目录中可以找到如下两个jar包:
2、放入日志输出控制文件:将文件log4j2.xml直接放到项目的src下。log4j2配置文件是XML文件,不再支持properties文件。默认的文件名为log4j2.xml。其存放的位置为classpath中。
<?xml version="1.0" encoding="UTF-8"?> <configuration status="OFF"> <appenders> <Console name="myConsole" target="SYSTEM_OUT"> <PatternLayout pattern="[%-5p][%d{yyyy-MM-dd HH:mm:ss}] [%c %L] %m%n" /> </Console> <File name="myLogFile" fileName="log/test.log" append="true"> <PatternLayout pattern="[%-5p][%d{yyyy-MM-dd HH:mm:ss}] [%c %L] %m%n"/> </File> <RollingFile name="myRollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout pattern="[%-5p][%d{yyyy-MM-dd HH:mm:ss}] [%c %L] %m%n"/> <SizeBasedTriggeringPolicy size="2KB"/> </RollingFile> </appenders> <loggers> <!-- <logger name="全限定类名或接口名" level="info"> <appender-ref ref="myConsole" /> </logger> --> <root level="trace"> <appender-ref ref="myConsole" /> <!-- <appender-ref ref="myLogFile" /> --> <!-- <appender-ref ref="myRollingFile" /> --> </root> </loggers> </configuration>
3、代码中实现日志记录:
在要输出日志的类中创建日志对象Logger,并通过Logger的方法在代码中加入日志输出语句。该日志对象是通过静态类LogManager的getLogger()方法获取的。
注意:Logger和LogManager均为org.apache.logging.log4j包中的类,并非org.apache.log4j包中的。
package com.eason.log4j2;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;public class MyMain { public static void main(String[] args) { Logger logger = LogManager.getLogger(MyMain.class); logger.debug("this is info message"); logger.info("this is debug message"); logger.warn("this is warn message"); logger.error("this is error message"); }}
5.2 日志输出控制文件分析
log4j2配置文件是XML文件,不再支持properties文件,默认的文件名为log4j2.xml。其存放的位置为classpath中。
若没有设置log4j2.xml,则系统会使用默认的日志配置,只会输出到控制台error级别的信息。