栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

websocket实现方法日志实时查询

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

websocket实现方法日志实时查询

        本次方法的核心概念是通过redis生成唯一key值(没有放出来),然后通过前端获取这个唯一的key带入到方法请求中,然后服务器通过这个key生成此次方法生成唯一的日志文件,websocket接口通过线程实时读取key文件返回内容。
1、通过logback生成日志工具类
package utils;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
import ch.qos.logback.core.util.FileSize;
import ch.qos.logback.core.util.OptionHelper;
import cn.sunline.dds.common.framework.constants.SocketLog;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;


public class LoggerBuilder {  
  
    private static final Map container = new HashMap<>();

    private static SocketLog socketLog;

    public static Logger getLogger(String key) {
        Logger logger = container.get(key);
        if(logger != null) {
            return logger;
        }
        synchronized (LoggerBuilder.class) {
            logger = container.get(key);
            if(logger != null) {
                return logger;
            }
            logger = build(key);
            container.put(key,logger);
        }
        return logger;
    }
    //删除container中的log
    public static void close(String key) {
        if (container.containsKey(key)) {
            container.remove(key);
        }
    }
  
    private static Logger build(String key) {
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();  
        Logger logger = context.getLogger("FILELOGGER");
        logger.setAdditive(false);  
        RollingFileAppender appender = new RollingFileAppender();  
        appender.setContext(context);  
        appender.setName("FILELOGGER");
        appender.setFile(OptionHelper.substVars("/logs/"+ key + ".log",context));
        appender.setAppend(true);  
        appender.setPrudent(false);
        //重命名日志文件
        SizeAndTimeBasedRollingPolicy policy = new SizeAndTimeBasedRollingPolicy();
        String fp = OptionHelper.substVars("/logs/" + key + ".log.%d{yyyy-MM-dd}.%i",context);
        policy.setMaxFileSize(FileSize.valueOf("128MB"));
        policy.setFileNamePattern(fp);
        policy.setMaxHistory(7);
        policy.setTotalSizeCap(FileSize.valueOf("32GB"));
        policy.setParent(appender);
        policy.setContext(context);
        policy.start();
  
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();  
        encoder.setContext(context);  
        encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n");
        encoder.start();  
  
        appender.setRollingPolicy(policy);  
        appender.setEncoder(encoder);  
        appender.start();  
        logger.addAppender(appender);  
        return logger;  
    }
}
 2、构建websocket方法
package socket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;


@ServerEndpoint("/log/{key}")
@Component
public class LogWebSocket {
    private final Logger logger = LoggerFactory.getLogger(LogWebSocket.class);

    
    private static final AtomicInteger ONLINE_COUNT = new AtomicInteger(0);
    
    private static final String PROPERTY = System.getProperty("user.dir");

    
    private static final Map CLIENTS = new ConcurrentHashMap<>();

    
    @OnOpen
    public void onOpen(Session session,@PathParam("key")String key) {
        try {
            System.out.println("------------------key------------------:"+key);
            // 建立连接梳理 加 1
            ONLINE_COUNT.incrementAndGet();
            // 将当前创建的session 存储起来
            CLIENTS.put(session.getId(), session);
            logger.info("有新窗口打开连接加入:{},当前正在查询总数为:{}", session.getId(), ONLINE_COUNT.get());
            String url = PROPERTY+ "/logs/"+key+".log";
            LogFileTailer tailer = new LogFileTailer(url);
            tailer.addListener(log -> {
                try {
//                    session.getBasicRemote().sendText(log + "
"); session.getBasicRemote().sendText(log); } catch (IOException e) { e.printStackTrace(); } }); tailer.start(); } catch (Exception e) { e.printStackTrace(); } } @OnClose public void onClose(Session session) { // 建立连接梳理 减 1 ONLINE_COUNT.decrementAndGet(); // 删除缓存起来的session CLIENTS.remove(session.getId()); logger.info("有一窗口连接关闭:{},当前正在开发总数为:{}", session.getId(), ONLINE_COUNT.get()); } @OnError public void onError(Session session, Throwable error) { error.printStackTrace(); // 建立连接梳理 减 1 ONLINE_COUNT.decrementAndGet(); // 删除缓存起来的session CLIENTS.remove(session.getId()); logger.error("发生错误,删除当前session:{},剩余正在总数为:{}", session.getId(), ONLINE_COUNT.get()); } }
3、日志监听获取
package socket;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.function.Consumer;


public class LogFileTailer extends Thread {

	private File logfile;

	private Consumer callback;

	
	private boolean tailing = true;

	
	public LogFileTailer(String file) {
		logfile = new File(file);

	}

	
	public void Tailing(boolean tailing) {
		this.tailing = tailing;

	}

	
	public void addListener(Consumer callback) {
		this.callback = callback;
	}

	@Override
	public void run() {
		
		long filePointer =0;
		try {
			RandomAccessFile file  = new RandomAccessFile(logfile, "r");
			while (tailing) {
				long fileLength = logfile.length();
				if (fileLength < filePointer) {
					file = new RandomAccessFile(logfile, "r");
					filePointer = 0;
				}
				if (fileLength > filePointer) {
					file.seek(filePointer);
					String line = file.readLine();

					while (line != null) {
						line = new String(line.getBytes("ISO-8859-1"), "utf-8");
						if (callback != null){
							callback.accept(line);
						}
						line = file.readLine();
					}

					filePointer = file.getFilePointer();
				}

//				sleep(sampleInterval);
			}

			file.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
4、问题补充
SpringBoot中需要注入bean,通过注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint。
要注意:如果使用独立的servlet容器,而不是直接使用springboot的内置容器,
就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理,所以在注入
ServerEndpointExporter时需要增加一些配置
package conf;

import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;


@Configuration
public class WebSocketConfig implements ServletContextInitializer {

    
	@Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize", String.valueOf(10 * 1024 * 1024));
        servletContext.setInitParameter("org.apache.tomcat.websocket.binaryBufferSize", String.valueOf(10 * 1024 * 1024));
    }
}

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/848222.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号