SpringBoot实战(八)集成 Logback

2023-11-16

1. 简介

Logback:是由 log4j 创始人设计的一个开源日志组件

Logback 模块:

  • logback-core:提供了 Logback 的核心功能,是另外两个组件的基础。
  • logback-classic:实现了 Slf4j 的 API,所以当想配合 Slf4j 使用时,需要引入 logback-classic。
  • logback-access:为了集成 Servlet 环境而准备的,可提供 HTTP-access 的日志接口。

Logback 是要与 Slf4j 结合起来使用。

Slf4j: Simple Logging Facade for Java,充当各种日志框架(例如:java.util.loggin、logback、log4j)的简单外观或抽象,允许最终用户在部署时插入所需的日志框架。

2. 项目结构

3. 配置文件

3.1 Maven

spring boot依赖:

在 Web 项目中,我们直接引入 spring-boot-starter-web 依赖即可。因为 spring-boot-starter-web 包含 spring-boot-starter 包含 spring-boot-starter-logging,所以我们只需要引入 web 组件即可。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

spring native依赖:

<properties>
	<slf4j.version>1.7.32</slf4j.version>
    <logback.version>1.2.5</logback.version>
</properties>
<dependencies>
	<!-- slf4j -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>

    <!-- logback -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>${logback.version}</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-access</artifactId>
        <version>${logback.version}</version>
    </dependency>
</dependencies>

3.2 logback-spring.xml

注意:这里使用了 spring.profiles.active,那么配置文件中必须要指定该配置,不然日志会不输出!

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <contextName>${APP_NAME}</contextName>
    <springProperty name="APP_NAME" scope="context" source="spring.application.name"/>
    <springProperty name="LOG_FILE" scope="context" source="logging.file" defaultValue="../logs"/>
    <springProperty name="LOG_POINT_FILE" scope="context" source="logging.file" defaultValue="../logs/point"/>
    <springProperty name="LOG_MAXFILESIZE" scope="context" source="logback.filesize" defaultValue="50MB"/>
    <springProperty name="LOG_FILEMAXDAY" scope="context" source="logback.filemaxday" defaultValue="7"/>
    <springProperty name="ServerIP" scope="context" source="spring.cloud.client.ip-address" defaultValue="0.0.0.0"/>
    <springProperty name="ServerPort" scope="context" source="server.port" defaultValue="0000"/>

    <!-- 彩色日志 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex"
                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx"
                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>

    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} [%clr(%X{traceId}){yellow},%clr(%X{X-B3-TraceId}){yellow}] %clr(%level){blue} %clr(%logger){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!--              value="[${APP_NAME}:${ServerIP}:${ServerPort}] %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} [%clr(%X{traceId}){yellow},%clr(%X{X-B3-TraceId}){yellow}] %clr(%level){blue} %clr(${PID}){magenta} %clr([%thread]){orange} %clr(%logger){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/> -->
    <property name="CONSOLE_LOG_PATTERN_NO_COLOR"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId},%X{X-B3-TraceId}] %level %logger %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>

    <!-- 控制台日志 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <withJansi>true</withJansi>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="com.demo.example.config.MyLogBackFilter"/>
    </appender>

    <!-- 按照每天生成常规日志文件 -->
    <!-- 不用的时候注释掉,防止生成无用的空白文件 -->
<!--    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
<!--        <file>${LOG_FILE}/${APP_NAME}-error.log</file>-->
<!--        &lt;!&ndash; 基于时间的分包策略 &ndash;&gt;-->
<!--        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">-->
<!--            <fileNamePattern>${LOG_FILE}/${APP_NAME}-error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
<!--            <maxFileSize>100MB</maxFileSize>-->
<!--            &lt;!&ndash;保留时间,单位:天&ndash;&gt;-->
<!--            <maxHistory>60</maxHistory>-->
<!--        </rollingPolicy>-->
<!--        <encoder>-->
<!--            <pattern>${CONSOLE_LOG_PATTERN_NO_COLOR}</pattern>-->
<!--            <charset>UTF-8</charset>-->
<!--        </encoder>-->
<!--        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">-->
<!--            <MaxFileSize>100MB</MaxFileSize>-->
<!--        </triggeringPolicy>-->
<!--        <filter class="ch.qos.logback.classic.filter.LevelFilter">&lt;!&ndash; 只打印错误日志 &ndash;&gt;-->
<!--            <level>ERROR</level>-->
<!--            <onMatch>ACCEPT</onMatch>-->
<!--            <onMismatch>DENY</onMismatch>-->
<!--        </filter>-->
<!--    </appender>-->

    <!-- 按照每天生成常规日志文件 -->
    <!-- 不用的时候注释掉,防止生成无用的空白文件 -->
<!--    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
<!--        <file>${LOG_FILE}/${APP_NAME}-info.log</file>-->
<!--        &lt;!&ndash; 基于时间的分包策略 &ndash;&gt;-->
<!--        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">-->
<!--            <fileNamePattern>${LOG_FILE}/${APP_NAME}-info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
<!--            <maxFileSize>100MB</maxFileSize>-->
<!--            &lt;!&ndash;保留时间,单位:天&ndash;&gt;-->
<!--            <maxHistory>60</maxHistory>-->
<!--        </rollingPolicy>-->
<!--        <encoder>-->
<!--            <pattern>${CONSOLE_LOG_PATTERN_NO_COLOR}</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>-->

    <!-- 按照每天生成常规日志文件 -->
    <appender name="ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}/${APP_NAME}/${APP_NAME}.jar.log</file>
        <!-- 基于时间的分包策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}/${APP_NAME}/${APP_NAME}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <!--保留时间,单位:天-->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN_NO_COLOR}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 增加无关日志的显示等级 -->
    <logger name="com.ulisesbocchio" level="INFO"/>
    <logger name="com.netflix" level="INFO"/>
    <logger name="com.zaxxer.hikari" level="INFO"/>
    <logger name="com.baomidou" level="INFO"/>
    <logger name="org" level="INFO"/>
    <logger name="_org" level="INFO"/>
    <logger name="io" level="INFO"/>

    <!-- 设置输出级别 -->
    <!-- 如果不需要根据环境区分配置,则不需要使用springPorfile -->
<!--    <root>-->
<!--        <appender-ref ref="STDOUT"/>-->
<!--        <appender-ref ref="ALL"/>-->
<!--    </root>-->

    <!-- 根据环境区分 -->
    <!-- 设置输出级别,开发环境(根据spring.profiles.active判断) -->
    <springProfile name="dev">
        <root level="DEBUG">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="ALL"/>
<!--            <appender-ref ref="ERROR"/>-->
<!--            <appender-ref ref="INFO"/>-->
        </root>
    </springProfile>

    <!-- 设置输出级别,生产环境(根据spring.profiles.active判断) -->
    <springProfile name="prod">
        <root level="DEBUG">
<!--            <appender-ref ref="STDOUT"/>-->
            <appender-ref ref="ALL"/>
<!--            <appender-ref ref="ERROR"/>-->
<!--            <appender-ref ref="INFO"/>-->
        </root>
    </springProfile>
</configuration>

3.3 application.yml

spring:
  application:
    name: spring-boot-logback # 用于生成日志文件名
  profiles:
    active: dev # 用于根据环境输出不同日志级别

4. 自定义输出级别

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

import java.util.Arrays;
import java.util.List;

/**
 * <p> @Title MyLogBackFilter
 * <p> @Description 定制控制台日志过滤器
 *
 * @author ACGkaka
 * @date 2022/1/6 11:15
 */
public class MyLogBackFilter extends Filter<ILoggingEvent> {

    private final List<Level> SHOW_LEVELS = Arrays.asList(Level.ERROR, Level.WARN, Level.INFO, Level.DEBUG, Level.TRACE);

    @Override
    public FilterReply decide(ILoggingEvent event) {
        // 指定打印日志类(供控制台用)
        if (event.getLoggerName().contains("org.springframework.boot")
                && !event.getLoggerName().contains("org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration")
                && !event.getLoggerName().contains("org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration")) {
            // 打印启动信息
            return FilterReply.ACCEPT;
        } else if (SHOW_LEVELS.contains(event.getLevel())) {
            // 打印异常信息
            return FilterReply.ACCEPT;
        } else {
            return FilterReply.DENY;
        }
    }
}

5. 项目地址

Github:https://github.com/ACGkaka/SpringBootExamples/tree/main/springboot-logback

测试地址:http://localhost:8080/tUser/findAll

指定日志路径: java -jar -Dlogging.file=/home/app/data/weblogs

6. 部分内容没有输出到日志文件中问题处理

e.printStackTrace() 和 System.out.println() 不会输出到日志。

如果要输出到日志,需要增加如下依赖:

<!-- System.out System.err 转 info -->
<dependency>
    <groupId>uk.org.lidalia</groupId>
    <artifactId>sysout-over-slf4j</artifactId>
    <version>1.0.2</version>
</dependency>

启动类中进行如下设置:

public static void main(String[] args) {
    // 加入这行代码时system.out输出为info日志
    SysOutOverSLF4J.sendSystemOutAndErrToSLF4J();
    // 启动应用
    SpringApplication.run(SpringbootDemoApplication.class, args);
}

7.根据开发、测试、生产环境采用不同的配置

修改SpringBoot项目中 application.yml 文件,来加载不同的logback.xml文件。

loggin:
	# 这里替换成你的logback配置文件名称,classpath:不能丢
	config: classpath:logback-dev.xml

8.补充1:控制台和日志文件中都不输出日志

问题分析:

在这里插入图片描述

这是因为 logback-spring.xml 配置文件中使用了 <springProfile> 标签,当 spring.profiles.active 配置没有设置的时候,logback 不知道应该加载哪个配置,所以干脆不输出日志了。

解决方案:

修改系统配置文件,增加spring.profiles.active 配置即可。

9.补充2:启动报错java.lang.ClassNotFoundException: org.fusesource.jansi.WindowsAnsiOutputStream

虽然报错之后程序也正常启动了,但是我们还是要解决这个问题。

报错截图:

在这里插入图片描述
详细报错信息:

Connected to the target VM, address: '127.0.0.1:58824', transport: 'socket'
22:22:30,546 |-INFO in ch.qos.logback.classic.LoggerContext[APP_NAME_IS_UNDEFINED] - Could NOT find resource [logback-test.xml]
22:22:30,547 |-INFO in ch.qos.logback.classic.LoggerContext[APP_NAME_IS_UNDEFINED] - Could NOT find resource [logback.groovy]
22:22:30,548 |-INFO in ch.qos.logback.classic.LoggerContext[APP_NAME_IS_UNDEFINED] - Found resource [logback.xml] at [file:/D:/IdeaProjects/SpringBootExamples/springboot-logback/logback-integration/log-spring-boot-starter/target/classes/logback.xml]
22:22:30,677 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
22:22:30,689 |-INFO in ch.qos.logback.classic.joran.action.ContextNameAction - Setting logger context name as [APP_NAME_IS_UNDEFINED]
22:22:30,695 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:87 - no applicable action for [springProperty], current ElementPath  is [[configuration][springProperty]]
22:22:30,696 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@5:99 - no applicable action for [springProperty], current ElementPath  is [[configuration][springProperty]]
22:22:30,696 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@6:111 - no applicable action for [springProperty], current ElementPath  is [[configuration][springProperty]]
22:22:30,696 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@7:107 - no applicable action for [springProperty], current ElementPath  is [[configuration][springProperty]]
22:22:30,696 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@8:105 - no applicable action for [springProperty], current ElementPath  is [[configuration][springProperty]]
22:22:30,696 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@9:117 - no applicable action for [springProperty], current ElementPath  is [[configuration][springProperty]]
22:22:30,696 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@10:97 - no applicable action for [springProperty], current ElementPath  is [[configuration][springProperty]]
22:22:30,696 |-INFO in ch.qos.logback.core.joran.action.ConversionRuleAction - registering conversion word clr with class [org.springframework.boot.logging.logback.ColorConverter]
22:22:30,696 |-INFO in ch.qos.logback.core.joran.action.ConversionRuleAction - registering conversion word wex with class [org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter]
22:22:30,696 |-INFO in ch.qos.logback.core.joran.action.ConversionRuleAction - registering conversion word wEx with class [org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter]
22:22:30,701 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
22:22:30,704 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
22:22:30,707 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
22:22:30,756 |-INFO in ch.qos.logback.core.ConsoleAppender[STDOUT] - Enabling JANSI WindowsAnsiOutputStream for the console.
22:22:30,758 |-WARN in ch.qos.logback.core.ConsoleAppender[STDOUT] - Failed to create WindowsAnsiOutputStream. Falling back on the default stream. ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type org.fusesource.jansi.WindowsAnsiOutputStream
	at ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type org.fusesource.jansi.WindowsAnsiOutputStream
	at 	at ch.qos.logback.core.util.OptionHelper.instantiateByClassNameAndParameter(OptionHelper.java:69)
	at 	at ch.qos.logback.core.util.OptionHelper.instantiateByClassNameAndParameter(OptionHelper.java:40)
	at 	at ch.qos.logback.core.ConsoleAppender.getTargetStreamForWindows(ConsoleAppender.java:88)
	at 	at ch.qos.logback.core.ConsoleAppender.start(ConsoleAppender.java:79)
	at 	at ch.qos.logback.core.joran.action.AppenderAction.end(AppenderAction.java:90)
	at 	at ch.qos.logback.core.joran.spi.Interpreter.callEndAction(Interpreter.java:309)
	at 	at ch.qos.logback.core.joran.spi.Interpreter.endElement(Interpreter.java:193)
	at 	at ch.qos.logback.core.joran.spi.Interpreter.endElement(Interpreter.java:179)
	at 	at ch.qos.logback.core.joran.spi.EventPlayer.play(EventPlayer.java:62)
	at 	at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:165)
	at 	at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:152)
	at 	at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:110)
	at 	at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:53)
	at 	at ch.qos.logback.classic.util.ContextInitializer.configureByResource(ContextInitializer.java:75)
	at 	at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:150)
	at 	at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
	at 	at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
	at 	at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
	at 	at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
	at 	at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:417)
	at 	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:362)
	at 	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:388)
	at 	at uk.org.lidalia.sysoutslf4j.context.LoggingSystemRegister.<clinit>(LoggingSystemRegister.java:35)
	at 	at uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J.<clinit>(SysOutOverSLF4J.java:48)
	at 	at com.demo.TLogEurekaApplication.main(TLogEurekaApplication.java:14)
Caused by: java.lang.ClassNotFoundException: org.fusesource.jansi.WindowsAnsiOutputStream
	at 	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at 	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at 	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at 	at ch.qos.logback.core.util.OptionHelper.instantiateByClassNameAndParameter(OptionHelper.java:56)
	at 	... 24 common frames omitted

解决方案:

其实这种情况只是一个logback的重命名问题,将 logback.xml 文件名修改为 logback-spring.xml 就好了。

logback.xml --> logback-spring.xml

整理完毕,完结撒花~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot实战(八)集成 Logback 的相关文章

随机推荐

  • git submodule拉取子模块最新代码

    转载请注明出处 https blog csdn net hhhhhhhhhhkkkkkkkkkk article details 122698629 之前由于对git子模块操作不熟悉 碰到子模块更新代码了本地死活拉取不到最新代码的问题 在网
  • 快速下载arxiv论文

    国内镜像站 http xxx itp ac cn 获得需要下载的论文id号 官网上会显示论文id 例如下载论文GAN的id为 1406 2661 那么 直接在浏览器上访问网址 http xxx itp ac cn pdf 1406 2661
  • 国密SKF库调用开发指南(一)

    针对支持国密算法USB KEY设备的应用 国家颁布一个行业标准 智能密码钥匙应用接口规范 GM T0016 2012 市面上销售的国密算法的USB KEY设备也都 其实也是必须 支持这个接口规范 因此 只要根据这个规范开发的应用程序 就可以
  • 李开复:数位革命——创新创业的黄金时代

    李开复 数位革命 创新创业的黄金时代 创新工场观点 数位革命 今天的创业时代比任何一个历史时期都能带来更多的机会 何谓 数位革命 看创新工场创始人 董事长兼首席执行官李开复老师如何从我们身处这个时代的六个现象中 看出变革 看出机会 未来是年
  • Vue脚手架的使用

    1 全局安装 vue cli 仅第一次执行 npm install g vue cli 再次输入vue 如果出现版本号 则成功 2 切换到要创建项目的目录 使用命令创建项目 vue create xxxx 3 启动项目 npm run se
  • Egret的2D摄像机实现

    一个Egret的正交摄像机的简单实现 主要功能大致如下 可参考根据实际进行调整 module Camera 一个正交摄像机demo export class Camera 摄像机显示的对象 实际是镜头所对应的世界 m container e
  • OpenCV机器视觉-图片卷积

    图片卷积 图像滤波是尽量保留图像细节特征的条件下对目标图像的噪声进行抑制 是图像预处理中不可缺少的操作 其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性 线性滤波是图像处理最基本的方法 它允许我们对图像进行处理 产生很多不同的
  • 【微信小程序入门到精通】— button 和 image 超详细讲解

    目录 前言 一 button 组件 1 1 指定按钮 属性值 type 1 2 改变按钮尺寸 属性值 size 1 3 使按钮镂空 属性值 plain 1 4 补充 二 image 组件 2 1 构建图片控件 image 2 2 指定图片缩
  • python数据容器--列表的常用操作

    数据容器List 列表的常用操作 List列表的常用操作 1 查找某元素在列表内的下标索引 列表 index 元素 mylist itcast itheima python index mylist index itcast print i
  • 指针的删除

    1 在链表中 将某个指针delete 指向该指针的那个指针的next 不会自动赋值为NULL 需要手动赋值 2 删掉 某指针所指向的内存 该指针仍然可以使用 下面是一个带头指针的单向链表 void Stack Pop int value i
  • 每日一考错题整理

    1 JDK JRE JVM三者之间的关系 以及JDK JRE包含的主要结构有哪些 JDK JRE Java开发工具 javac exe java exe javadoc exe JRE JVM JAVASE核心类库 2 标识符的命名规范有哪
  • JDK8新特性之双冒号 :: 用法及详解

    JDK8新特性之双冒号 用法及详解 转自 https cloud tencent com developer article 1404786 JDK8的新特性有很多 最亮眼的当属函数式编程的语法糖 本文主要讲解下双冒号 的用法 类名 方法名
  • ubuntu:android studio 安装adb调试工具

    adb安装 apt get install android tools adb 远程连接 adb connect 172 26 0 119 5555 遇到端口占用 yangwenlong title71 Android AndroidPro
  • 微服务全栈:深入核心组件与开发技巧

    文章目录 1 服务注册与发现 1 1 客户端注册 ZooKeeper 1 2 第三方注册 独立的服务Registrar 1 3 客户端发现 1 4 服务端发现 1 5 Consul 1 6 Eureka 1 7 SmartStack 1 8
  • firefox 火狐浏览器安装java插件

    由于工作中用到决策引擎产品 FICO Blaze 该产品展示决策流 决策树 决策表等组件是依托的applet 需要浏览器启用java插件 经常碰到明明电脑上装了java 但是浏览器的附加组件中却没有显示 经过一下午的折腾发现了以下几条限制
  • SpringCloud系列教程(1)--开发环境的准备

    开发环境准备 eclipse apache maven 3 5 0 jdk1 8 说明 这个是本人的开发环境工具 也可以使用自己适应的环境 比如 IntelliJ IDEA 但是本系列以eclipse来简述 如果环境不会配置 请自行百度 因
  • Android Studio TraceView性能优化分析

    http blog csdn net androiddevelop article details 8223805 http www cnblogs com sunzn p 3192231 html Android 编程下的 TraceVi
  • ConstraintLayout各种居中设置

    1 全局居中 app layout constraintBottom toBottomOf parent app layout constraintEnd toEndOf parent app layout constraintStart
  • Python基于xlrd模块处理合并单元格

    Excel是我们日常工作中经常使用的电子表格软件 它可以方便地对数据进行整理 计算和分析 在Excel中 有时候需要将多个单元格合并成一个单元格 以便更好地展示数据 但是 在数据处理过程中 合并单元格也会带来不少麻烦 本文将介绍如何使用Py
  • SpringBoot实战(八)集成 Logback

    目录 1 简介 2 项目结构 3 配置文件 3 1 Maven 3 2 logback spring xml 3 3 application yml 4 自定义输出级别 5 项目地址 6 部分内容没有输出到日志文件中问题处理 7 根据开发