mirror of
https://github.com/gotoeasy/glogcenter.git
synced 2025-09-15 12:58:34 +08:00
0.9.0
This commit is contained in:
parent
b03ff7b39a
commit
ec5b41977f
181
glc-logback-appender/pom.xml
Normal file
181
glc-logback-appender/pom.xml
Normal file
@ -0,0 +1,181 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>top.gotoeasy</groupId>
|
||||
<artifactId>glc-logback-appender</artifactId>
|
||||
<version>0.9.0</version>
|
||||
<description>logback appender for glogcenter</description>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>aliyun-central</id>
|
||||
<name>aliyun-central Repository</name>
|
||||
<url>https://maven.aliyun.com/repository/central</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype-snapshot</id>
|
||||
<name>sonatype-snapshot Repository</name>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>always</updatePolicy>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<name>gotoeasy-aop</name>
|
||||
<url>https://gitlab.gotoeasy.top/gotoeasy/framework.git</url>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU Lesser General Public Licence</name>
|
||||
<url>http://www.gnu.org/licenses/lgpl.txt</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>青松</name>
|
||||
<email>gotoeasy@163.com</email>
|
||||
<organization>top.gotoeasy</organization>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<scm>
|
||||
<connection>scm:https://gitlab.gotoeasy.top/gotoeasy/framework.git</connection>
|
||||
<developerConnection>scm:https://gitlab.gotoeasy.top/gotoeasy/framework.git</developerConnection>
|
||||
<url>https://gitlab.gotoeasy.top/gotoeasy/framework.git</url>
|
||||
<tag>${project.version}</tag>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java-version>1.8</java-version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.11</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.rabbitmq</groupId>
|
||||
<artifactId>amqp-client</artifactId>
|
||||
<version>5.15.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.properties</include>
|
||||
<include>**/*.xml</include>
|
||||
<include>**/*.klass</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources/META-INF</directory>
|
||||
<targetPath>META-INF</targetPath>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<!-- Source -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Javadoc -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>sonatype</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>sonatype</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,264 @@
|
||||
package top.gotoeasy.framework.glc.logback.appender;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.rabbitmq.client.Connection;
|
||||
import com.rabbitmq.client.ConnectionFactory;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.AppenderBase;
|
||||
import ch.qos.logback.core.Layout;
|
||||
|
||||
/**
|
||||
* GLC是glogcenter缩写,一个golang实现的日志中心<br>
|
||||
* GlcAmqpAppender提供一种发送日志数据到RabbitMQ的方式(GLC则从RabbitMQ接收日志),适用于使用logback做日志管理的java项目
|
||||
*/
|
||||
public class GlcAmqpAppender extends AppenderBase<ILoggingEvent> {
|
||||
|
||||
// 自定义配置,需Getter和Setter方法
|
||||
private String amqpHost;
|
||||
private int amqpPort;
|
||||
private String amqpUser;
|
||||
private String amqpPassword;
|
||||
private String system;
|
||||
private Layout<ILoggingEvent> layout;
|
||||
|
||||
private int cnt = 0;
|
||||
private boolean enableGlc = true;
|
||||
|
||||
private ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
protected Connection connection = null;
|
||||
protected Channel channel = null;
|
||||
|
||||
protected synchronized void initConnectionChannel() throws Exception {
|
||||
if (this.channel != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Connection conn = null;
|
||||
Channel chan = null;
|
||||
try {
|
||||
ConnectionFactory factory = new ConnectionFactory(); // 创建一个连接工厂
|
||||
factory.setHost(amqpHost); // 工厂ip 连接rabbitmq的队列
|
||||
factory.setPort(amqpPort); // 端口
|
||||
factory.setUsername(amqpUser); // 用户名
|
||||
factory.setPassword(amqpPassword); // 密码
|
||||
conn = factory.newConnection(); // 创建连接
|
||||
chan = conn.createChannel(); // 获取信道
|
||||
|
||||
// 对列名称,
|
||||
// durable 是否持久化数据
|
||||
// exclusive 排他性,权限私有
|
||||
// autoDelete 是否自动删除
|
||||
// arguments
|
||||
chan.queueDeclare("glc-log-queue", false, false, false, null);
|
||||
} finally {
|
||||
this.connection = conn;
|
||||
this.channel = chan;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void append(ILoggingEvent event) {
|
||||
if (!enableGlc) {
|
||||
return; // 未启用时跳过
|
||||
}
|
||||
|
||||
if (event == null || !isStarted()) {
|
||||
if (cnt++ < 10) {
|
||||
System.err.println("日志事件为空或该Appender未被初始化");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 异步发送日志
|
||||
executor.execute(() -> {
|
||||
sendToRabbitMQ(layout.doLayout(event));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送日志到RabbitMQ<br>
|
||||
*
|
||||
* @param text 日志
|
||||
*/
|
||||
protected void sendToRabbitMQ(String text) {
|
||||
try {
|
||||
if (channel == null) {
|
||||
initConnectionChannel();
|
||||
}
|
||||
|
||||
String body = "{" + encodeStr("text") + ":" + encodeStr(text.trim());
|
||||
body += "," + encodeStr("date") + ":" + encodeStr(getDateString());
|
||||
body += "," + encodeStr("system") + ":" + encodeStr(getSystem());
|
||||
body += "}";
|
||||
|
||||
channel.basicPublish("", "glc-log-queue", null, body.getBytes("utf-8"));
|
||||
} catch (Exception e) {
|
||||
if (cnt++ < 10) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
resetConnectionChannel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (this.layout == null) {
|
||||
System.err.println("Layout未被初始化");
|
||||
}
|
||||
super.start();
|
||||
|
||||
// 优先使用环境变量设定
|
||||
String enable = System.getenv("GLC_ENABLE");
|
||||
if ("false".equalsIgnoreCase(enable) || "0".equals(enable)) {
|
||||
enableGlc = false;
|
||||
}
|
||||
String host = System.getenv("GLC_AMQP_HOST");
|
||||
if (host != null) {
|
||||
host = host.trim();
|
||||
if (!"".equals(host)) {
|
||||
setAmqpHost(host);
|
||||
}
|
||||
}
|
||||
String port = System.getenv("GLC_AMQP_PORT");
|
||||
if (port != null) {
|
||||
port = port.trim();
|
||||
if (!"".equals(port)) {
|
||||
setAmqpPort(Integer.valueOf(port));
|
||||
}
|
||||
}
|
||||
String user = System.getenv("GLC_AMQP_USER");
|
||||
if (user != null) {
|
||||
user = user.trim();
|
||||
if (!"".equals(user)) {
|
||||
setAmqpUser(user);
|
||||
}
|
||||
}
|
||||
String password = System.getenv("GLC_AMQP_PASSWORD");
|
||||
if (password != null) {
|
||||
password = password.trim();
|
||||
if (!"".equals(password)) {
|
||||
setAmqpPassword(password);
|
||||
}
|
||||
}
|
||||
String system = System.getenv("GLC_SYSTEM");
|
||||
if (system != null) {
|
||||
system = system.trim();
|
||||
if (!"".equals(system)) {
|
||||
setSystem(system);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (!isStarted()) {
|
||||
return;
|
||||
}
|
||||
super.stop();
|
||||
}
|
||||
|
||||
public String getAmqpHost() {
|
||||
return amqpHost;
|
||||
}
|
||||
|
||||
public void setAmqpHost(String amqpHost) {
|
||||
this.amqpHost = amqpHost;
|
||||
}
|
||||
|
||||
public int getAmqpPort() {
|
||||
return amqpPort;
|
||||
}
|
||||
|
||||
public void setAmqpPort(int amqpPort) {
|
||||
this.amqpPort = amqpPort;
|
||||
}
|
||||
|
||||
public String getAmqpUser() {
|
||||
return amqpUser;
|
||||
}
|
||||
|
||||
public void setAmqpUser(String amqpUser) {
|
||||
this.amqpUser = amqpUser;
|
||||
}
|
||||
|
||||
public String getAmqpPassword() {
|
||||
return amqpPassword;
|
||||
}
|
||||
|
||||
public void setAmqpPassword(String amqpPassword) {
|
||||
this.amqpPassword = amqpPassword;
|
||||
}
|
||||
|
||||
public Layout<ILoggingEvent> getLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void setLayout(Layout<ILoggingEvent> layout) {
|
||||
this.layout = layout;
|
||||
}
|
||||
|
||||
public void setSystem(String system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
public String getSystem() {
|
||||
return system == null ? "" : system;
|
||||
}
|
||||
|
||||
protected synchronized void resetConnectionChannel() {
|
||||
try {
|
||||
if (channel != null) {
|
||||
channel.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// ignore
|
||||
} finally {
|
||||
this.channel = null;
|
||||
}
|
||||
try {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// ignore
|
||||
} finally {
|
||||
this.connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
private String encodeStr(String str) {
|
||||
return "\"" + str.replaceAll("\"", "\\\\\"").replaceAll("\t", "\\\\t").replaceAll("\r", "\\\\r")
|
||||
.replaceAll("\n", "\\\\n") + "\"";
|
||||
}
|
||||
|
||||
private static String getDateString() {
|
||||
SimpleDateFormat sdf = getSimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
|
||||
private static Object lockObject = new Object();
|
||||
|
||||
private static SimpleDateFormat getSimpleDateFormat(String format) {
|
||||
SimpleDateFormat simpleDateFormat = threadLocal.get();
|
||||
if (simpleDateFormat == null) {
|
||||
synchronized (lockObject) {
|
||||
if (simpleDateFormat == null) {
|
||||
simpleDateFormat = new SimpleDateFormat(format);
|
||||
simpleDateFormat.setLenient(false);
|
||||
threadLocal.set(simpleDateFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
simpleDateFormat.applyPattern(format);
|
||||
return simpleDateFormat;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,220 @@
|
||||
package top.gotoeasy.framework.glc.logback.appender;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.AppenderBase;
|
||||
import ch.qos.logback.core.Layout;
|
||||
|
||||
/**
|
||||
* GLC是glogcenter缩写,一个golang实现的日志中心<br>
|
||||
* GlcHttpJsonAppender提供一种http提交Json数据的方式发送日志到GLC,适用于使用logback做日志管理的java项目<br>
|
||||
* 仅简易实现为主,若是性能要求高日志量大的场景,应选用其他比如消息队列之类的Appender
|
||||
*/
|
||||
public class GlcHttpJsonAppender extends AppenderBase<ILoggingEvent> {
|
||||
|
||||
// 自定义配置,需Getter和Setter方法
|
||||
private String glcApiUrl;
|
||||
private String glcApiKey;
|
||||
private String system = "default";
|
||||
private Layout<ILoggingEvent> layout;
|
||||
|
||||
private String headerKey;
|
||||
private String headerVal;
|
||||
|
||||
private int cnt = 0;
|
||||
private boolean enableGlc = true;
|
||||
|
||||
private ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
@Override
|
||||
protected void append(ILoggingEvent event) {
|
||||
if (!enableGlc) {
|
||||
return; // 未启用时跳过
|
||||
}
|
||||
|
||||
if (event == null || !isStarted()) {
|
||||
if (cnt++ < 10) {
|
||||
System.err.println("日志事件为空或该Appender未被初始化");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 异步发送日志到GLC
|
||||
executor.execute(() -> {
|
||||
submitToGlogCenter(layout.doLayout(event));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送日志到GLC<br>
|
||||
* 为不依赖第三方包,仅作java原生包简单实现,性能较差<br>
|
||||
* 实际使用时若有性能问题可继承重写实现
|
||||
*
|
||||
* @param text 日志
|
||||
*/
|
||||
protected void submitToGlogCenter(String text) {
|
||||
|
||||
DataOutputStream dos = null;
|
||||
try {
|
||||
String body = "{" + encodeStr("text") + ":" + encodeStr(text.trim());
|
||||
body += "," + encodeStr("date") + ":" + encodeStr(getDateString());
|
||||
body += "," + encodeStr("system") + ":" + encodeStr(getSystem());
|
||||
body += "}";
|
||||
|
||||
URL url = new URL(glcApiUrl);
|
||||
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
||||
// 设置header
|
||||
if (headerKey != null && !"".equals(headerVal)) {
|
||||
connection.setRequestProperty(headerKey, headerVal);
|
||||
}
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
connection.setUseCaches(false);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
// 发送日志数据
|
||||
connection.connect();
|
||||
dos = new DataOutputStream(connection.getOutputStream());
|
||||
dos.write(body.getBytes("utf-8"));
|
||||
dos.flush();
|
||||
// 接收响应内筒
|
||||
connection.getContent();
|
||||
connection.disconnect();
|
||||
} catch (Exception e) {
|
||||
if (cnt++ < 10) {
|
||||
System.err.println("[GLC日志发送异常][地址:" + glcApiUrl + "][异常信息:" + e.getMessage() + "]");
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (dos != null) {
|
||||
dos.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (this.layout == null) {
|
||||
System.err.println("Layout未被初始化");
|
||||
}
|
||||
super.start();
|
||||
|
||||
// 优先使用环境变量设定
|
||||
String enable = System.getenv("GLC_ENABLE");
|
||||
if ("false".equalsIgnoreCase(enable) || "0".equals(enable)) {
|
||||
enableGlc = false;
|
||||
}
|
||||
String apiUrl = System.getenv("GLC_API_URL");
|
||||
if (apiUrl != null) {
|
||||
apiUrl = apiUrl.trim();
|
||||
if (!"".equals(apiUrl)) {
|
||||
setGlcApiUrl(apiUrl);
|
||||
}
|
||||
}
|
||||
|
||||
String apiKey = System.getenv("GLC_API_KEY");
|
||||
if (apiKey != null) {
|
||||
apiKey = apiKey.trim();
|
||||
if (!"".equals(apiKey)) {
|
||||
setGlcApiKey(apiKey);
|
||||
}
|
||||
}
|
||||
|
||||
String system = System.getenv("GLC_SYSTEM");
|
||||
if (system != null) {
|
||||
system = system.trim();
|
||||
if (!"".equals(system)) {
|
||||
setSystem(system);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (!isStarted()) {
|
||||
return;
|
||||
}
|
||||
super.stop();
|
||||
}
|
||||
|
||||
public Layout<ILoggingEvent> getLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void setLayout(Layout<ILoggingEvent> layout) {
|
||||
this.layout = layout;
|
||||
}
|
||||
|
||||
public String GetGlcApiUrl() {
|
||||
return glcApiUrl;
|
||||
}
|
||||
|
||||
public void setGlcApiUrl(String glcApiUrl) {
|
||||
this.glcApiUrl = glcApiUrl;
|
||||
}
|
||||
|
||||
public String GetGlcApiKey() {
|
||||
return glcApiKey;
|
||||
}
|
||||
|
||||
public void setSystem(String system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
public String getSystem() {
|
||||
return system == null ? "" : system;
|
||||
}
|
||||
|
||||
public void setGlcApiKey(String glcApiKey) {
|
||||
this.glcApiKey = glcApiKey;
|
||||
|
||||
String key = glcApiKey.split(":")[0];
|
||||
String value = glcApiKey.substring(key.length() + 1).trim();
|
||||
key = key.trim();
|
||||
if (!"".equals(key)) {
|
||||
headerKey = key;
|
||||
headerVal = value;
|
||||
}
|
||||
}
|
||||
|
||||
private String encodeStr(String str) {
|
||||
return "\"" + str.replaceAll("\"", "\\\\\"").replaceAll("\t", "\\\\t").replaceAll("\r", "\\\\r")
|
||||
.replaceAll("\n", "\\\\n") + "\"";
|
||||
}
|
||||
|
||||
private static String getDateString() {
|
||||
SimpleDateFormat sdf = getSimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
|
||||
private static Object lockObject = new Object();
|
||||
|
||||
private static SimpleDateFormat getSimpleDateFormat(String format) {
|
||||
SimpleDateFormat simpleDateFormat = threadLocal.get();
|
||||
if (simpleDateFormat == null) {
|
||||
synchronized (lockObject) {
|
||||
if (simpleDateFormat == null) {
|
||||
simpleDateFormat = new SimpleDateFormat(format);
|
||||
simpleDateFormat.setLenient(false);
|
||||
threadLocal.set(simpleDateFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
simpleDateFormat.applyPattern(format);
|
||||
return simpleDateFormat;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user