1.6 项目调试技巧及日志使用

187 阅读6分钟

项目调试技巧

image-20220705162214824.png

状态码

常见状态码:

image-20220705175813332.png

成功响应

200 OK

请求成功。成功的含义取决于 HTTP 方法:

  • GET: 资源已被提取并在消息正文中传输。
  • HEAD: 实体标头位于消息正文中。
  • PUT or POST: 描述动作结果的资源在消息体中传输。
  • TRACE: 消息正文包含服务器收到的请求消息。

另外,这里介绍一下重定向:

image-20220705180630598.png

比如说浏览器请求删除,然后服务器执行删除操作之后应该返回给浏览器什么界面呢,应该返回查询结果以便查看请求删除数据是否被删除,这个时候的话让服务器的 “删除” 操作去调用 “查询” 操作的话是不合适的,因为这是两个业务,之间不应该产生耦合,这个时候服务器会传给浏览器一个状态码并附加一个路径,然后浏览器通过这个路径调 “查询” 方法,服务器再去执行 “查询方法“ 然后返回结果给浏览器。这就是重定向,这种方式比起 controller之间 互相调用降低了耦合。


重定向消息

303 See Other

服务器发送此响应,以指示客户端通过一个 GET 请求在另一个 URI 中获取所请求的资源。

客户端响应

404 Not Found

服务器找不到请求的资源。在浏览器中,这意味着无法识别 URL。在 API 中,这也可能意味着端点有效,但资源本身不存在。服务器也可以发送此响应,而不是 403 Forbidden,以向未经授权的客户端隐藏资源的存在。这个响应代码可能是最广为人知的,因为它经常出现在网络上。

服务端响应

500 Internal Server Error

服务器遇到了不知道如何处理的情况。

501 Not Implemented

服务器不支持请求方法,因此无法处理。服务器需要支持的唯二方法(因此不能返回此代码)是 GET and HEAD.

502 Bad Gateway

此错误响应表明服务器作为网关需要得到一个处理这个请求的响应,但是得到一个错误的响应。

服务端调试

向下执行一行 按:F8

进入当前行所调的方法内部 按:F7

如果想要直接跳转到下一个断点 按:Alt + F9 (注:如果没有下一个断点直接执行到底)

image-20220705200954403.png

image-20220705201207436.png

客户端调试

客户端调试就是 js 调试,就是打断点调试

客户端的代码运行在浏览器上,我们想给客户端打断点应该在哪打呢

向下执行一行 F10

进入到某一个方法内部 F11

执行到下一个断点 F8

image-20220705202959111.png

设置日志级别

logback.qos.ch

image-20220705204303467.png

trace 、debug、info、warn、error

严重性越来越高,级别越来预高

比如启用了 info 级别,只有 info 、warn、error级别会被打印出来,trace、debug会被忽视

使用测试类

接下来用测试类使用一下日志

在配置文件里声明一下启用什么级别的日志

在 application.properties 配置文件中加上下面这句话(意思是启用 debug 级别以上的日志都打印出来)

# logger
logging.level.com.nowcoder.community=debug

image-20220706094619177.png

要记录日志,首先要记得实例化记录日志的接口Logger

@SpringBootTest
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = CommunityApplication.class)
public class LoggerTests {

    private static final Logger logger = LoggerFactory.getLogger(LoggerTests.class);

    @Test
    public void testLogger(){
        System.out.println(logger.getName());       // 这个只是看一下Logger的名字,并不是日志

        logger.debug("debug log");
        logger.info("info log");
        logger.warn("warn log");
        logger.error("error log");
    }
}

image-20220706092724007.png

# 注意
按理说 debug 级别的话 trace 级别的日志是不会输出的,但是我所执行的程序里面 debug 日志级别trace 级别
的日志却输出了,其他日志级别的倒是遵循高日志输出。

测试结果:

image-20220706094738524.png

将日志存到指定的文件

上面这种方式是将日志打印在控制台上,这种方式只要程序关闭日志就不会留存下来。所以为了能够长久的保存这些日志,便于对日志的分析,我们经常需要另外把日志存到指定的文件里,下面演示一下

我们只需要在 application.properties 配置文件中配置指定路径即可

logging.file.name=d:/work/data/nowcoder/community.log

image-20220706100346536.png

执行测试代码之后

image-20220706100442572.png

上面这种日志打印到文件中的方式比较简单,实际上在应用当中还会做的比这个更复杂一点。

简单的打到一个 log 文件里,这个文件可能会非常的大,而且这个文件里面会混杂着各种级别的日志,不方便我们去做分析。我们在实际开发的过程中往往是把日志按照不同的级别存到不同的文件里,这样的话如果只想分析 “错误”,就看 error.log,最好是一个文件达到一定的空间后,再拆分出另外一个文件,接下来演示一下

想达到上面的效果,我们需要写一个 log 所对应的xml文件 logback-spring.xml ,且xml文件必须是这个名字,这个文件比较复杂,用的时候直接粘到项目里,会改就行了,把 logback-spring.xml 配置文件放到 resources 根路径下(注:这个日志配置文件必须叫这个名字,且放在resources 目录下)

使用下面的配置文件配置日志就不需要在 application.properties 配置文件中配置日志了

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <contextName>community</contextName>
    <property name="LOG_PATH" value="D:/work/data"/>
    <property name="APPDIR" value="community"/>

    <!-- error file -->
    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${APPDIR}/log_error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/${APPDIR}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>5MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- warn file -->
    <appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${APPDIR}/log_warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/${APPDIR}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>5MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- info file -->
    <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${APPDIR}/log_info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/${APPDIR}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>5MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- console -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
    </appender>

    <logger name="com.nowcoder.community" level="debug"/>

    <root level="info">
        <appender-ref ref="FILE_ERROR"/>
        <appender-ref ref="FILE_WARN"/>
        <appender-ref ref="FILE_INFO"/>
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

image-20220706105552317.png

image-20220706110245779.png

image-20220706110958678.png

上面的文件在使用到自己项目的时候需要改动的地方就是上面的路径包名

接下来运行一个测试类测试一下

image-20220706111728427.png

总结

在开发程序的时候,如果发现有问题,首先应该 1. 看状态码,大概定位一下是服务器端还是客户端有问题, 然后通过断点去跟踪或者去看一 2. 看这个日志,当然能看日志就先看日志,日志还是找不到问题就 3.跟踪一下。