Java Tips

JUL

现在大家大多都是用SLF4J,但其实JUL也很不错,最明显的好处就是你不用引用额外的包。
这里列出相关的配置

package org.yx.base;

import java.io.IOException;
import java.io.InputStream;
import java.util.logging.LogManager;

public class Config {
    private static final String PROPERTY_FILE = "/properties/log.properties";

    public void configLog() throws IOException {
        LogManager manager = LogManager.getLogManager();
        try (InputStream inputStream = this.getClass().getResourceAsStream(PROPERTY_FILE)) {
            manager.readConfiguration(inputStream);
        }
    }
}

作为替代, 你也可以不用上面的Config类,你可以采用-Djava.util.logging.config.file=XXX 作为JVM的启动参数,但这种方式你就不能把properties文件打包到jar里了。 参考 OverviewLogManager

log.properties

-Your Project
 -src
  -main
   +java
   -resources
    -properties
     +log.properties
# 输出到文件和控制台
handlers=java.util.logging.FileHandler,java.util.logging.ConsoleHandler
# root日志输出级别 level
.level=ALL
# 控制台输出级别和格式
java.util.logging.ConsoleHandler.level=DEBUG
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
# 文件输出级别和地址
java.util.logging.FileHandler.level=INFO
java.util.logging.FileHandler.pattern=./server.log
#限制文件的大小(50000字节)
java.util.logging.FileHandler.limit=50000
#过滤,总共保存1个文件,接着猜覆盖
java.util.logging.FileHandler.count=1
#XMLFormatter是以xml样式输出,SimpleFormatter是以普通样式输出
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
#指定是否应该将 FileHandler 追加到任何现有文件上(false会覆盖,但默认为false)。
java.util.logging.FileHandler.append=true

使用

    private static final Logger LOG = Logger.getLogger("");

    public static void main(String[] args) throws IOException {
        Config config = new Config();
        config.configLog();//Config only once.

        LOG.info("texting logging");
    }

SLF4J

依赖

plugins {
    id 'java'
}

group 'org.yx'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    // https://mvnrepository.com/artifact/org.postgresql/postgresql
    implementation group: 'org.postgresql', name: 'postgresql', version: '42.3.1'

    // https://mvnrepository.com/artifact/org.slf4j/slf4j-api
    implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.0-alpha5'

    // https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
    implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.0-alpha12'

}

jar {
    manifest {
        attributes["Main-Class"] = "org.yx.Main"
    }
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
}

logback.xml (放在resources目录下)

<configuration packagingData="true">
    <shutdownHook/>

    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{"yyyy-MM-dd'T'HH:mm:ss,SSSXXX"} [%thread] %p %c{1} [%t] %m%n</pattern>
        </encoder>
    </appender>

    <appender name="AsyncLogFile" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="LogFile"/>
    </appender>
    <appender name="LogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>./server.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>./server-%d{yyy-MM-dd}.log.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{"yyyy-MM-dd'T'HH:mm:ss,SSSXXX"} [%thread] %p %c{1} [%t] %m%n</pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="Console"/>
        <appender-ref ref="AsyncLogFile"/>
    </root>
</configuration>

其中 packagingData="true"会把异常stacktrace 中 源文件所在包打印出来 参考

DataSource

通常使用数据库要获得Connection, 如果你不使用JPA,你可以用一下方式获得DataSource/Connection

//Postgresql
        PGPoolingDataSource source = new PGPoolingDataSource();
        source.setDataSourceName("A Data Source");
        source.setServerName("127.0.0.1");
        source.setDatabaseName("text");
        source.setUser("user");
        source.setPassword("pwd");
        source.setMaxConnections(2);
        source.getConnection();
//SAP hana
    DataSourceSAP ds = new DataSourceSAP();
    ds.setUrl("jdbc:sap://127.0.0.1:30010?reconnect=true");
    ds.setUser("user");
    ds.setPassword("pwd");

有时你可能希望运行一个sql文件的批处理,但注意,你只能一句一句的添加到Statement.addBatch,每一句都要是合法的SQL语句,而不能添加包含;分隔的一个sql文件的整个内容

package org.yx.base;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

public class SQLBatch {
    private static final Logger LOGGER = LoggerFactory.getLogger(SQLBatch.class);
    private String sql;

    public SQLBatch(String fileName) throws IOException {
        sql = FileUtils.readFileToString(new File(fileName), StandardCharsets.UTF_8);
        preProcessSql();
    }

    public SQLBatch(InputStream in) throws IOException {
        sql = IOUtils.toString(in, StandardCharsets.UTF_8);
        preProcessSql();
    }

    private void preProcessSql() {
        sql = sql.replaceAll("\r", "");
        sql = sql.replaceAll("\n", "");
    }


    public void exec() throws SQLException {

        try (Connection con = DBConfig.getInstance().getConnection()) {
            con.setAutoCommit(false);
            try (Statement stmt = con.createStatement()) {
                for (String one : sql.split(";")) {
                    stmt.addBatch(one);
                }
                stmt.executeBatch();
            } catch (SQLException e) {
                con.rollback();
                LOGGER.error(e.getMessage(), e);
            }
            con.commit();
        }
    }
}

快速搭建微服务

下面利用Consul和Spring快速搭建一个微服务框架

安装好Consul后

启动Consul后访问 http://localhost:8500

consul agent -dev -data-dir=tmp

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.5'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group 'org.example'
version '1.0'

repositories {
    mavenCentral()
}

ext {
    set('springCloudVersion', "2021.0.5")
}

dependencies {
    implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation(group: 'org.springframework.boot', name: 'spring-boot-starter-web')

    //implementation group: 'org.postgresql', name: 'postgresql', version: '42.2.9'

}
dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

Main.java

package org.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@RestController
public class Main {

    static Logger LOG = LoggerFactory.getLogger(Main.class);
    private final RestTemplate restTemplate = new RestTemplate();
    @Autowired
    private DiscoveryClient discoveryClient;

    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }

    @RequestMapping("/test")
    public String home() {
        return "Hello World!";
    }

    @RequestMapping("/remote")
    public String remote() {
        var list = discoveryClient.getInstances("myApp");
        if (!CollectionUtils.isEmpty(list)) {
            var str = list.get(0).getUri().toString();
            LOG.info(str);
            var ret = restTemplate.getForObject(str + "/test", String.class);
            LOG.info("rest call [{}] return: [{}]", str, ret);

            return ret;
        }
        return null;
    }

}

application.yml

spring:
  cloud:
    service-registry:
      auto-registration:
        enabled: true
    consul:
      host: localhost
      port: 8500
      discovery:
        healthCheckPath: /actuator/health
        healthCheckInterval: 5s
  application:
    name: myApp-1


build另一个jar包之前把application.name改为myApp

java -Dserver.port=8889 -jar build/libs/test-Consul-1.0.jar
java -Dserver.port=8888 -jar build/libs/test-Consul-1.0.jar

然后访问http://localhost:8889/remote即可

Log如下

2022-11-23 13:46:15.606  INFO 364639 --- [nio-8889-exec-3] org.example.Main                         : http://192.168.75.128:8888
2022-11-23 13:46:15.655  INFO 364639 --- [nio-8889-exec-3] org.example.Main                         : rest call [http://192.168.75.128:8888] return: [Hello World!]

posted @ 2018-05-24 16:53  开学五年级了  阅读(2270)  评论(0)    收藏  举报