Java项目调试技巧及版本控制
开发项目中,调试是必不可少的。
本篇博客从以下4个方面介绍项目调试技巧:
- 响应状态码的含义
 - 服务端断点调试技巧
 - 客户端断点调试技巧
 - 设置日志级别,并将日志输出到不同的终端
 以及,最后简单的介绍了一下git的使用。
1. 项目调试技巧
项目调试过程中,web项目首先看HTTP状态响应码,找是客户端还是服务端的错误,看看日志信息有没有错误信息,如果没有找到,进行断点调试,这是一个大概的流程。
1.1 响应状态码的含义
接下来介绍几个最常见的响应状态码,参考网址:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
HTTP 响应状态代码指示特定 HTTP 请求是否已成功完成。响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599)。状态代码由 section 10 of RFC 2616定义
打开任意一个网址,都会有如下信息:

200 OK  (成功响应)
请求成功。成功的含义取决于HTTP方法:
- GET:资源已被提取并在消息正文中传输。
 - HEAD:实体标头位于消息正文中。
 - POST:描述动作结果的资源在消息体中传输。
 - TRACE:消息正文包含服务器收到的请求消息
 
302 Found   (重定向)
请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
介绍一下重定向:假如说网页上进行删除功能,这个时候删除完毕,是不需要返回一个html的,但是生活中常见的会发生什么?一般删除之后,网页会回到一个地址,比如说首页或者说回到查询页面。这个就是重新进行定位。另外一个例子:我们注册之后,一般直接会跳转到登录页面。

服务器进行删除功能之后,返回302状态码,以及一个新的路径。至于为什么删除之后没有直接进行查询功能呢?项目中不同功能之间要保持松耦合,不能形成依赖。
404 Not Found   (客户端响应)
请求失败,请求所希望得到的资源未被在服务器上发现。没有信息能够告诉用户这个状况到底是暂时的还是永久的。假如服务器知道情况的话,应当使用410状态码来告知旧资源因为某些内部的配置机制问题,已经永久的不可用,而且没有任何可以跳转的地址。404这个状态码被广泛应用于当服务器不想揭示到底为何请求被拒绝或者没有其他适合的响应可用的情况下。
500 Internal Server Error    (服务端响应)
服务器遇到了不知道如何处理的情况。这时候应该去检查服务端的程序。
1.2 服务端断点调试技巧
以本人博客的后端项目开发代码为例,介绍IDEA的调试技巧。

设置断点,进入debug模式
访问URL,浏览器会一直处理,因为服务端程序停留在断点那一步

调试界面如下(step over只直接跳转到程序的下一行,不进入方法,step into则是进入方法进行跳转下一行):

如果想跳过循环条件,毕竟循环可能会循环很多次。可以进行Resume Program恢复程序,比如,你在第20行和25行有两个断点,当前运行至第20行,按F9,则运行到下一个断点(即第25行),再按F9,则运行完整个流程,因为后面已经没有断点了。
其中,debug部分,View Breakpoints可以进行断点管理,可以看到所有断点,进行是否使用的设置。

1.3 客户端断点调试技巧

浏览器F12进入开发者模式,其中
Elements调试的是页面,前端部分会用到。Console可以看到JS输出的结果。Source可以看客户端执行的代码。

其实这里设置断点和IDEA相同,点击代码行左侧设置断点,当使用该部分功能时,会呈现如下效果:

在Source右侧,和IDEA相同,还是有step over和step into等操作。逻辑都是相同的。

1.4 设置日志级别
SpringBoot的日志工具是logback,官网为:http://logback.qos.ch/

logger中不同的日志级别:
- trace跟踪级别
 - debug调试级别
 - info普通级别
 - warn警告级别
 - error错误级别
 
这五个级别从低到高顺序排列。例:开启Info级别,则trace和debug不会打印出来,只有更高级别的日志会打印出来。级别设置是为了提高性能。
接下来举个例子:(SpringBoot中在application.properties设置Logger级别即可)
logging.level.com.nowcoder.community=debug
举测试类:
public class LoggerTests {
    //为了便于所有的方法去调用,一般设置为静态,不可改变的,注意使用org.slf4j包下的
    //传入的类即logger的名字,一般传入当前类,这样便于区别不同的Logger
    private static final Logger logger = LoggerFactory.getLogger(LoggerTests.class);
    @Test
    public void testLogger() {
        System.out.println(logger.getName());
        logger.debug("debug log");
        logger.info("info log");
        logger.warn("warn log");
        logger.error("error log");
    }
}
这是在logger为debug级别下进行的测试:

更高级别的log都有显示。
级别改为warn后:

一般来说,项目开发过程中采用debug级日志,方便调试。上线后一般采用更高级别。并且上线后都不会有控制台了,这就需要我们把日志文件给打印出来。
1.4.1. 直接在application.properties中配置
过程:在properties进行配置
logging.file.path=sp.log
该配置会在同级目录下生成sp.log文件夹,里面存储spring.log
(不知为何,logging.file这句配置在我这里失效了,暂未找到原因,SpringBoot2.5.1)
这种方式会混杂各种类型的日志,而且可能文件比较大,建议将各种级别的日志放在不同的文件中,介绍第二种配置方式。
1.4.2 logback-spring.xml配置
在resources目录下,SpringBoot会自动识别该命名的.xml文件并进行配置,注意如果命名不同则不会识别。
以error级别log文件配置为例:(已加注释,请阅读源码)
<contextName>community</contextName>
<!-- log文件存放地址,这里相当于一个string -->
<property name="LOG_PATH" value="D:/javawork/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">
        <!-- 命名格式,%d为日期, %i是一个变量,如0,1,2等 -->
        <fileNamePattern>${LOG_PATH}/${APPDIR}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <!-- 一个Log最大为5MB,如果存不下再存新的 -->
            <maxFileSize>5MB</maxFileSize>
        </timeBasedFileNamingAndTriggeringPolicy>
        <!-- 最长存储时间30天 -->
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <!-- 以追加的方式存储而不是覆盖 -->
    <append>true</append>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <!-- 定义日志输出格式%d日期,%level级别, [%thread]哪个线程执行,%logger{10}logger所处的类,[%file:%line] 所处哪个文件多少行 -->
        <!-- %msg%n消息内容 -->
        <pattern>%d %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
        <charset>utf-8</charset>
    </encoder>
    <!-- 过滤器,过滤error级日志 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>error</level>
        <!-- 这里的意思是匹配到就接收,不匹配就拒绝 -->
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
</appender>
其他级别的Log文件配置类似,可自行配置。
其中,也可以配置如何打印控制台Log信息,例:
<!-- 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>
在.xml文件末尾需要声明:
<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>
root代表项目根目录,因为项目中包含着非常多的包,所以级别为info即可,debug级将会多出许多不必要的log。其中,logger会将日志信息传给root,root再根据appender进行打印。具体信息可参考官方网站,没有细说。
中间4行代表启用上述的error等各个级别的文件配置。
项目中的日志配置参考该模板即可。
2. 版本控制
分布式版本控制系统,在这类系统中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。

这部分介绍git相关。便于备份代码,或者在开发流程中共享代码。是团队开发中非常重要的工具。
首先介绍相关命令(windows命令):个人建议使用git.bash,使用linux命令,毕竟linux在将来的开发中还会有应用。

参考网址:Git官网
如果想详细了解git知识,建议阅读(中文版):https://git-scm.com/book/zh/v2
具体原理及应用可见:B站尚硅谷教学视频
我个人的操作一般是:
- 在github上创建仓库,因为一般仓库中都有readme这些信息文件,所以将仓库克隆到本地(你需要上传的仓库地址)命令:git clone url
 - 将需要上传的文件复制进克隆的文件夹里
 - cd 文件地址,输入命令
 
git add . //添加所有文件
git commit -m "需要提交的信息" //提交到本地仓库
git push -u origin main //将本地仓库push到远程的main分支,也可以push到master分支
因为我个人使用了两个github,所以一个采用ssh密钥,上述方式介绍的是http协议上传方式,使用账号密码即可。
除此之外的方式还有利用fetch和push等等,我介绍的方式比较适用于初学者。
IDEA配置git:

改为自己的git路径。
IDEA的VCS中有git的各个操作,首先如图Create Git Repository,

然后Git中有commit,选中要提交的文件,不用选中全部,比如maven那些包其实没必要提交。
commit之后,Git中有push,填上远程仓库的url以及登录仓库即可。
Java项目调试技巧及版本控制的更多相关文章
- Java常用调试技巧(转)
		
调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷.对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序.本文介绍了Java程序员必知的10个调试技巧, ...
 - Java开发调试技巧及Eclipse快捷键使用方法
		
1. 快捷键 syso 通过打印输出来调试,println可接受object型的参数,能输出任何类型 Syso输出的是黑色字体,代表的是Debug的信息 Syse,输出的是红色字体,代表错误的输出信息 ...
 - Java web 调试技巧之查看浏览器中调试中的network
		
在java web开发过程中尤其后台开发经常需要查看浏览器调试中的network项:今天在开发在线预览系统时用到了flexpaper插件,这个插件会调用FlexPaperViewer.swf这个软件( ...
 - java与.net比较学习系列(1) 开发环境和常用调试技巧
		
最近因为公司项目要由.net平台转到java平台的原因,之前一直用.net的我不得不开始学习java了,刚开始听到说要转java的时候很抗拒,因为我想专注在.net平台上,不过这样也并不完全是坏事,通 ...
 - Myeclipse - Web项目转换技巧--处理Java项目、SVN非Web项目问题
		
喜欢从业的专注,七分学习的态度. 概述 对于Java调试,使用Eclipse习惯性的使用Junit调试,使用Myeclipse习惯性的将项目转成Web项目在Tomcat或Weblogic中调试,在My ...
 - 使用 Eclipse 调试 Java 程序的技巧
		
你应该看过一些如<关于调试的N件事>这类很流行的帖子 .假设我每天花费1小时在调试我的应用程序上的话,那累积起来的话也是很大量的时间.由于这个原因,用这些时间来重视并了解所有使我们调试更方 ...
 - java系列:《java核心技术 卷1》学习笔记,chapter 11 调试技巧
		
11. 6 调试技巧 1)一个不太为人所知却非常有效的技巧是在每个类中放一个main方法,这样就可以对每个类进行单元测试.这个方法可以保留,因为在java虚拟机只调用启动类的main方法. 2) ...
 - Java程序员应该知道的10个Eclipse调试技巧
		
Eclipse是众多Java程序员实用的开发工具,其中开发技巧也是繁多,但作为优秀的Java程序员,需要掌握最起码的调试技巧. 1 条件断点 2 异常断点 3 监视点 4 评估/检查 5 修改变量值 ...
 - Java开发小技巧(三):Maven多工程依赖项目
		
前言 本篇文章基于Java开发小技巧(二):自定义Maven依赖中创建的父工程project-monitor实现,运用我们自定义的依赖包进行多工程依赖项目的开发. 下面以多可执行Jar包项目的开发为例 ...
 
随机推荐
- ffmpeg architecture(上)
			
ffmpeg architecture(上) 目录 介绍 视频-您看到的是什么! 音频-您在听什么! 编解码器-缩小数据 容器-音频和视频的舒适场所 FFmpeg-命令行 FFmpeg命令行工具101 ...
 - 孟老板 BaseAdapter封装(四) PageHelper
			
BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...
 - 4,java数据结构和算法:双向链表 ,有序添加,正向遍历,反向遍历, 增删改查
			
直接上代码 //节点 class HeroNodeD{ int no; String name; String nickName; HeroNodeD pre;//前一节点 HeroNodeD nex ...
 - 提高GUI自动化测试稳定性解决方案
			
针对"GUI自动化测试稳定性问题"这个问题,最典型的情景就是:同样的测试用例,在同样的测试执行环境下,测试的结果有时是Success,有时是Fail,这严重降低了GUI测试的可信度 ...
 - CLR里的MethodTable,MethodDescChunk,MethodDesc,FixUpPreCode都是什么意思
			
一:看下面一些概念 1MethodTable MethodTable可以说在CLR里面无处不在,这个东西主要是作为对象的数据类型存在,主要包含了EEClass 模块地址,类型名称,模块路径等. 2.E ...
 - windows+R键的应用
			
windows+R:然后输入以下几个命令 1.cmd :用于Windows命令行操作,比如:ping某个网络,看看是不是通的,或者directory等等Windows命令行操作 2.远程桌面连接:ms ...
 - 温故而知新--day5
			
温故而知新--day5 ip地址 IP是英文Internet Protocol的缩写,意思是"网络之间互连的协议",也就是为计算机网络相互连接进行通信而设计的协议.当多个设备要进行 ...
 - javascript之一切都是对象
			
在学习的过程中,我们常常能听到这样一句话:一切皆是对象.那么这句话该如何理解呢?首先,我们要明确对象的概念.要明白除了基本数据类型都是对象. typeof操作符是大家经常使用的,我们常用它来检测给定变 ...
 - OpenMVG 系列 (1):入门简介
			
1 OpenMVG 简介 全称 Open Multiple View Geometry,是法国人 Pierre Moulon 读博期间开源的一个 C++ 库 最早版本 OpenMVG 0.1 是 ...
 - 不藏了,这些Java反射用法总结都告诉你们
			
摘要:Java反射是一种非常强大的机制,它可以在同一个系统中去检测内部的类的字段.方法和构造函数.它非常多的Java框架中,都大量应用了反射技术,如Hibernate和Spring.可以说,反射机制的 ...