发表于: 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-corespring-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 的相关知识及在项目中的使用


返回列表 返回列表
评论

    分享到