发表于: 2019-10-23 09:04:35
2 1222
啥也不说就是干!!!
今天完成的事情:
1、Junit
JUnit 是 Java 编写语言的单元测试框架,JUnit 促进了 “先测试后编码”的理念,强调建立测试数据的一段代码,可以先测试,然后再应用。这个方法就好比“测试一点,编码一点,测试一点,编码一点...” 增强了程序员的产量和程序的稳定性,可以减少程序员的压力和排错的时间。
JUnit 有如下特点:
一个开放的资源框架,用于编写和运行测试
提供注释来识别测试方法,提供断言来运行测试,提供测试运行来运行测试
JUnit 测试可以自动运行并且检查自身结果并提供即时反馈
JUnit 在进度条中显示进度。如果运行良好则是绿色;如果运行失败,则是红色
一般 IDE 为我们提供了 JUnit 运行环境,我们只需依赖 JUnit 框架,并编写需要的测试类及测试方法。
下面以之前的工程为例,编写 JUnit 测试方法。
首先添加 Maven 依赖:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
在项目工程下的 src/test/java 目录下编写 MainTest 文件,在该类中添加一个方法:
public void queryStudent2() throws PropertyVetoException {
StudentServiceImpl2 studentService = new StudentServiceImpl2();
Student student = studentService.queryById(6).get(0);
System.out.println(student.toString());
MyBatisUtil myBatisUtil = new MyBatisUtil();
SqlSession sqlSession = myBatisUtil.getSqlSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
List<Student> studentInfos= studentMapper.queryStudentById(5);
System.out.println("studnetInfos size---->"+studentInfos.size());
System.out.println("student info--->"+student);
}
并在该方法上标注 @Test 注解(以便 Junit 识别为测试方法),选中该方法,右键 Run 执行测试方法并查看测试结果:
也可以直接在 Terminal 窗口下执行
mvn test -Dtest=com.gerry.jushu.MainTest#queryStudent2
执行测试文件中的 queryStudent2 方法(参考之前章节 Maven Test 命令)
2、Log4j
Log4j 是一个使用 Java 语言编写的,可靠、快速、灵活的日志框架(API)
Log4j 主要由三部分组成:
loggers:负责采集日志信息。 appenders:负责将日志信息发布到不同地方。 layouts:负责以各种风格格式化日志信息。
论如何打印日志:https://www.jianshu.com/p/61e2eca2792a
为什么使用 Log4j 代替 System.out,当然是 Log4j 更加的强大,满足更多的需求。看一下它的优点:
1) 线程安全、速度优化、支持国际化。
2) 日志记录行为可在运行期通过配置文件设置。
3) 使用多个日志级别:ALL、TRACE、DEBUG、INFO、WARN、ERROR、FATAL。(级别顺序 ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF)
4) 通过扩展 Layout 类可轻松改变输出日志的格式。
5) 输出日志的目的和策略可通过实现 Appender 接口改变。
6) 失败即停止(不保证每一条日志都能发送到指定目的地)
记录日志也有其缺点,它会让应用变慢。假如输出太详细,可能会导致屏幕闪动。为了减轻这些影响,Log4j 被设计为可靠的,更快的和可扩展的。
如何在项目中使用 Log4j
1)添加 Maven 依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2) 添加 Log4j 配置文件 src/main/resource/log4j.properties
log4j.rootLogger= DEBUG,stdout,info
# ERROR OFF , R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
# Define the layout for info appender
log4j.logger.info=info
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%p %t %c - %m%n
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
#Set the name of the file
log4j.appender.info.File=log/loginfo.txt
# Set the immediate flush to true (default)
Log4j.appender.info.ImmediateFlush=true
# Set the threshold to info mode
Log4j.appender.info.Threshold=INFO
# Set the append to false, should not overwrite
Log4j.appender.info.Append=true
# Set the maximum file size before rollover
Log4j.appender.info.MaxFileSize=100KB
# Set the the backup index
Log4j.appender.info.MaxBackupIndex=2
# Set the the split date pattern index
log4j.appender.info.datePattern='.'yyyy-MM-dd
# Set the filter to INFO
log4j.appender.info.filter.infoFilter=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.info.filter.infoFilter.LevelMin=INFO
log4j.appender.info.filter.infoFilter.LevelMax=INFO
log4j.logger.com.mybatis=debug
log4j.logger.com.mybatis.common.jdbc.SimpleDataSource=debug
log4j.logger.com.mybatis.common.jdbc.ScriptRunner=debug
log4j.logger.com.mybatis.sqlmap.engine.impl.SqlMapClientDelegate=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
配置文件中的属性可参考官方文档,这里重点说一下怎么将日志记录到指定的文件中。
首先指定要输出的目标路径:
log4j.appender.info.File=log/loginfo.txt
还可以指定一下,通过 filter 来过滤具体记录哪个级别的日志:
log4j.appender.info.filter.infoFilter=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.info.filter.infoFilter.LevelMin=INFO
log4j.appender.info.filter.infoFilter.LevelMax=INFO
接下来将刚才测试方法中的 System.out 替换成 Log
static Logger logger = Logger.getLogger(MainTest.class.getName());
@Test
public void queryStudent2() throws PropertyVetoException {
// StudentServiceImpl2 studentService = new StudentServiceImpl2();
// Student student = studentService.queryById(6).get(0);
// System.out.println(student.toString());
MyBatisUtil myBatisUtil = new MyBatisUtil();
SqlSession sqlSession = myBatisUtil.getSqlSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
List<Student> studentInfos= studentMapper.queryStudentById(6);
logger.info("studnetInfos size---->"+studentInfos.size());
logger.info(studentInfos.get(0).toString());
}
执行测试方法,可以看到 log 记录已经显示
同时 log 文件已经保存至指定的位置:
以上是 Log4j 的使用。这里推荐一款 Intellij 一款插件 GrepConsole,配置控制台不同级别日志的颜色,以便很好地区分控制台各个级别的日志信息
Log4j2 跟 Log4j 使用方法类似,但是性能方面根据其官网宣称的优势有多线程下10几倍于log4j 1.x和logback的高吞吐量、可配置的审计型日志、基于插件架构的各种灵活配置等。如果已经掌握log4j 1.x,使用log4j2还是非常简单的。
添加相关依赖:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency> <!-- 桥接:告诉Slf4j使用Log4j2 -->
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.10</version>
</dependency>
同样也是得在 resource 目录下添加相应的配置文件:log4j2.xml。这里参考了网上的相对完整的配置
<Configuration status="OFF">
<Properties>
<!-- 配置日志文件输出目录 -->
<property name="trans_log_path" value="log/" />
<property name="file_size" value="5MB" />
<property name="file_encode" value="UTF-8" />
<property name="file_max_count" value="2000" />
<property name="file_dir">${sys:catalina.home}/logs/</property>
<property name="output_log_level">info</property><!-- 日志输出级别 -->
<property name="file_prefix">log_</property>
<property name="log_pattern" value="[gateway] %x %-5level %d{yyyy-MM-dd HH:mm:ss,SSS} [%t] %c.%M(%L) | %msg%xEx%n" />
</Properties>
<Appenders>
<!--这个输出控制台的配置 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY" />
<!--这个都知道是输出日志的格式 -->
<PatternLayout pattern="${log_pattern}" />
</Console>
<!-- 重要的是,如果有多个ThresholdFilter,那么Filters是必须的,同时在Filters中,首先要过滤不符合的日志级别,把不需要的首先DENY掉,然后再ACCEPT需要的日志级别,这个次序不能搞颠倒。 -->
<!-- 这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
<!-- 按日生成归档日志 -->
<!-- 设置日志格式并配置日志压缩格式(service.log.年份.gz) -->
<!-- 显示INFO级别的信息 -->
<RollingRandomAccessFile name="INFO_LOG" fileName="${trans_log_path}/${file_prefix}info.log" filePattern="${trans_log_path}/${file_prefix}info.log.%d{yyyy-MM-dd}.log.gz">
<PatternLayout>
<pattern>${log_pattern}</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<Filters>
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</RollingRandomAccessFile>
<!--如果需要配置多个Rollingfile地址,还需要在root下添加appender-ref ref="ERR_LOG"/> 只显示error级别的信息 -->
<RollingRandomAccessFile name="ERROR_LOG" fileName="${trans_log_path}/${file_prefix}error.log" filePattern="${trans_log_path}/${file_prefix}error.log.%d{yyyy-MM-dd}.log.gz">
<PatternLayout>
<pattern>${log_pattern}</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</RollingRandomAccessFile>
<!-- DEBUG日志格式 -->
<RollingRandomAccessFile name="DEBUG_LOG" fileName="${trans_log_path}/${file_prefix}debug.log" filePattern="${trans_log_path}/${file_prefix}debug.log.%d{yyyy-MM-dd}.log.gz">
<PatternLayout>
<pattern>${log_pattern}</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<Filters>
<ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
</Filters>
</RollingRandomAccessFile>
<!-- WARN_LOG日志格式 -->
<RollingRandomAccessFile name="WARN_LOG" fileName="${trans_log_path}/${file_prefix}warn.log" filePattern="${trans_log_path}/${file_prefix}warn.log.%d{yyyy-MM-dd}.log.gz">
<PatternLayout>
<pattern>${log_pattern}</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<Filters>
<ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</RollingRandomAccessFile>
</Appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
<Loggers>
<!-- 第三方日志系统 -->
<Logger name="org" level="error" additivity="false">
<AppenderRef ref="DEBUG_LOG" />
<AppenderRef ref="INFO_LOG" />
<AppenderRef ref="WARN_LOG" />
<AppenderRef ref="ERROR_LOG" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="net" level="error" additivity="false">
<AppenderRef ref="DEBUG_LOG" />
<AppenderRef ref="INFO_LOG" />
<AppenderRef ref="WARN_LOG" />
<AppenderRef ref="ERROR_LOG" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="org.apache" level="debug" additivity="false">
<AppenderRef ref="DEBUG_LOG" />
<AppenderRef ref="INFO_LOG" />
<AppenderRef ref="WARN_LOG" />
<AppenderRef ref="ERROR_LOG" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="org.springframework.web" level="debug" additivity="false">
<AppenderRef ref="DEBUG_LOG" />
<AppenderRef ref="INFO_LOG" />
<AppenderRef ref="WARN_LOG" />
<AppenderRef ref="ERROR_LOG" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="org.springframework" level="error" additivity="false">
<AppenderRef ref="DEBUG_LOG" />
<AppenderRef ref="INFO_LOG" />
<AppenderRef ref="WARN_LOG" />
<AppenderRef ref="ERROR_LOG" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="org.displaytag" level="error" additivity="false">
<AppenderRef ref="DEBUG_LOG" />
<AppenderRef ref="INFO_LOG" />
<AppenderRef ref="WARN_LOG" />
<AppenderRef ref="ERROR_LOG" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="org.springframework.transaction" level="debug" additivity="false">
<AppenderRef ref="DEBUG_LOG" />
<AppenderRef ref="INFO_LOG" />
<AppenderRef ref="WARN_LOG" />
<AppenderRef ref="ERROR_LOG" />
<AppenderRef ref="Console" />
</Logger>
<Logger name="com.msds" level="debug" additivity="false">
<AppenderRef ref="DEBUG_LOG" />
<AppenderRef ref="INFO_LOG" />
<AppenderRef ref="WARN_LOG" />
<AppenderRef ref="ERROR_LOG" />
<AppenderRef ref="Console" />
</Logger>
<!-- 配置日志的根节点,建立一个默认的root的logger,需要在root的level中指定输出的级别 -->
<Root level="${output_log_level}">
<appender-ref ref="DEBUG_LOG" />
<appender-ref ref="INFO_LOG" />
<appender-ref ref="WARN_LOG" />
<appender-ref ref="ERROR_LOG" />
<appender-ref ref="Console" />
</Root>
</Loggers>
</Configuration>
然后再测试类中使用相应的日志记录:
同时响应的日志记录也输出到了文件中
3、Spring 环境搭建
Spring 是一个 IOC(DI)和 AOP 容器框架,它包含并管理了应用对象的声明周期。可以使用 XML 和 Java 注解组合这些对象。
Inverse of Control(IOC) 控制反转。本来属于 Java 程序里构建对象的功能交由容器(Spring)接管
Spring 在这里提供了一个容器,我们在 xml 文件里定义各个对象的依赖关系,由容器完成对象的构建,当我们 Java 代码中需要使用某个实例的时候可以从容器里面获取
Aspect-OrientedProgramming 面向切面编程。同时把应用的业务逻辑和系统的服务分离开来。
AOP 将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面(Crosscutting enterprise concerns)。例如,所有大中型应用都要涉及的持久化管理(persistent)、事务管理(Tracsaction Management)、安全管理(Security)、日志管理(Loggin)和调试管理(Debuggin)等。
实现方式主要是:
1)动态代理技术,利用截取消息的方式,对该消息进行装饰,取代原有对象的行为
2)静态植入,引入特定的语法创建 “方面”,从而使得编译器可以在编译期间植入有关“方面”的代码
Maven 添加相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>
spring-context 实现了 Spring 注入容器并且依赖:spring-core, spring-expression, spring-aop 以及 spring-beans。这些依赖包使容器可以支持 Spring 的一些核心技术:Spring 核心组件, Spring EL 表达式 (SpEL), 面向切面编程, JavaBean 机制。
基于 XML 文件配置 Bean
在 resources 文件夹下创建 applicationContext.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--
配置bean
class:bean的全类名,通过反射的方法在IOC容器中创建Bean。所以要求Bean中必须有无参的构造器。
id:标识容器中的bean。id 唯一
-->
<bean id="student" class="com.gerry.jnshu.Student">
</bean>
</beans>
获取定义好的 Bean 实例
public class App {
public static void main(String[] args) {
private static final Logger logger = LogManager.getLogger(App.class)
//HelloWorld helloWorld = new HelloWorld();
//helloWorld.setName("Spring");
//1.创建Spring的IOC容器对象
//ApplicationContext代表IOC容器
//ClassPathXmlApplicationContext是ApplicationContext代表IOC容器接口实现类,从类路径下加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从IOC中获取Beab实例Student student = (Student) ctx.getBean("student")
logger.info(student);
}
}
今天由于时间关系,先写到这里
明天计划的事情:
1、Spring 依赖注入
2、Spring 基于 注解的配置
3、Spring AOP
4、Spring 实现 JDBCTemplate及 Mybatis
遇到的问题:
暂无
收获:
学习了 Log4j Junit 单元测试,初步搭建了 Spring 环境,接下来还需要学习 Spring 的相关知识及在项目中的使用
评论