Skip to content

Commit

Permalink
新增Web端日志控制台 http://127.0.0.1:8000
Browse files Browse the repository at this point in the history
  • Loading branch information
剑器近 authored and Yezhihao committed Apr 8, 2019
1 parent b4b53fb commit 2050b67
Show file tree
Hide file tree
Showing 17 changed files with 398 additions and 46 deletions.
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/yzh/framework/TCPServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ public TCPServer(int port, byte delimiter, HandlerMapper handlerMapper, MessageD
this.inboundHandler = new TCPServerHandler(delimiter, messageDecoder, messageEncoder, handlerMapper);
}

public TCPServer(int port, byte delimiter, HandlerMapper handlerMapper, MessageDecoder messageDecoder, MessageEncoder messageEncoder, org.yzh.framework.log.Logger logger) {
this();
this.port = port;
this.delimiter = delimiter;
this.inboundHandler = new TCPServerHandler(delimiter, messageDecoder, messageEncoder, handlerMapper, logger);
}

private void bind() throws Exception {
this.bossGroup = new NioEventLoopGroup();
this.workerGroup = new NioEventLoopGroup();
Expand Down
41 changes: 27 additions & 14 deletions src/main/java/org/yzh/framework/TCPServerHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yzh.framework.codec.MessageDecoder;
import org.yzh.framework.codec.MessageEncoder;
import org.yzh.framework.log.Logger;
import org.yzh.framework.mapping.Handler;
import org.yzh.framework.mapping.HandlerMapper;
import org.yzh.framework.message.AbstractHeader;
import org.yzh.framework.message.PackageData;
import org.yzh.framework.session.Session;
import org.yzh.framework.session.SessionManager;
Expand All @@ -21,10 +21,10 @@
@ChannelHandler.Sharable
public class TCPServerHandler extends ChannelInboundHandlerAdapter {

private static final Logger logger = LoggerFactory.getLogger(TCPServerHandler.class.getSimpleName());

private final SessionManager sessionManager = SessionManager.getInstance();

private Logger logger;

private HandlerMapper handlerMapper;

private MessageDecoder decoder;
Expand All @@ -38,8 +38,18 @@ public TCPServerHandler(byte delimiter, MessageDecoder decoder, MessageEncoder e
this.decoder = decoder;
this.encoder = encoder;
this.handlerMapper = handlerMapper;
this.logger = new Logger();
}

public TCPServerHandler(byte delimiter, MessageDecoder decoder, MessageEncoder encoder, HandlerMapper handlerMapper, Logger logger) {
this.delimiter = delimiter;
this.decoder = decoder;
this.encoder = encoder;
this.handlerMapper = handlerMapper;
this.logger = logger;
}


@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
Expand All @@ -53,18 +63,19 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
Handler handler = handlerMapper.getHandler(type);

if (handler == null) {
logger.info("in 未知消息 {} {}", channel.id().asShortText(), ByteBufUtil.hexDump(headerBodyBuf));
logger.logMessage("i 未知消息", null, ByteBufUtil.hexDump(headerBodyBuf));
return;
}

logger.info("in {} {} {}", handler, channel.id().asShortText(), ByteBufUtil.hexDump(headerBodyBuf));

Class<?>[] types = handler.getTargetParameterTypes();
Class<? extends PackageData> targetClass = (Class<? extends PackageData>) types[0];

PackageData packageData = decoder.decode(headerBodyBuf, Header.class, targetClass);

Object result;
headerBodyBuf.resetReaderIndex();
logger.logMessage("i " + handler.toString(), packageData, ByteBufUtil.hexDump(headerBodyBuf));

PackageData<? extends AbstractHeader> result;
if (types.length == 1) {
result = handler.invoke(packageData);
} else {
Expand All @@ -73,8 +84,8 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception

if (result == null)
return;
ByteBuf resultBuf = encoder.encode((PackageData) result);
logger.info("out {} {} {}", handler, channel.id().asShortText(), ByteBufUtil.hexDump(resultBuf));
ByteBuf resultBuf = encoder.encode(result);
logger.logMessage("o " + handler.toString(), result, ByteBufUtil.hexDump(resultBuf));
ByteBuf allResultBuf = Unpooled.wrappedBuffer(Unpooled.wrappedBuffer(new byte[]{delimiter}), resultBuf, Unpooled.wrappedBuffer(new byte[]{delimiter}));
ChannelFuture future = channel.writeAndFlush(allResultBuf).sync();
} finally {
Expand All @@ -86,21 +97,23 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
public void channelActive(ChannelHandlerContext ctx) {
Session session = Session.buildSession(ctx.channel());
sessionManager.put(session.getId(), session);
logger.debug("终端连接 {} ip={}", session, ctx.channel().remoteAddress());
logger.logEvent("终端连接", session);
}

@Override
public void channelInactive(ChannelHandlerContext ctx) {
String sessionId = Session.buildId(ctx.channel());
Session session = sessionManager.removeBySessionId(sessionId);
logger.debug("断开连接 {} ip={}", session, ctx.channel().remoteAddress());
logger.logEvent("断开连接", session);
ctx.channel().close();
// ctx.close();
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {
logger.error("发生异常:{}", e.getMessage());
String sessionId = Session.buildId(ctx.channel());
Session session = sessionManager.removeBySessionId(sessionId);
logger.logEvent("发生异常", session);
e.printStackTrace();
}

Expand All @@ -110,7 +123,7 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.READER_IDLE) {
Session session = this.sessionManager.removeBySessionId(Session.buildId(ctx.channel()));
logger.error("服务器主动断开连接:{}", session);
logger.logEvent("服务器主动断开连接", session);
ctx.close();
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/org/yzh/framework/codec/MessageEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.yzh.framework.commons.transform.Bcd;
import org.yzh.framework.message.AbstractHeader;
import org.yzh.framework.message.PackageData;
import org.yzh.web.jt808.dto.basics.Header;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
Expand All @@ -29,13 +28,13 @@ public MessageEncoder(Charset charset) {
/** 签名 */
public abstract ByteBuf sign(ByteBuf buf);

public ByteBuf encode(PackageData<Header> body) {
ByteBuf bodyBuf = encode(Unpooled.buffer(512), body);
public ByteBuf encode(PackageData<T> body) {
ByteBuf bodyBuf = encode(Unpooled.buffer(256), body);

Header header = body.getHeader();
AbstractHeader header = body.getHeader();
header.setBodyLength(bodyBuf.readableBytes());

ByteBuf headerBuf = encode(Unpooled.buffer(100), header);
ByteBuf headerBuf = encode(Unpooled.buffer(16), header);

ByteBuf buf = Unpooled.wrappedBuffer(headerBuf, bodyBuf);

Expand Down
23 changes: 23 additions & 0 deletions src/main/java/org/yzh/framework/log/Logger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.yzh.framework.log;

import org.slf4j.LoggerFactory;
import org.yzh.framework.TCPServerHandler;
import org.yzh.framework.message.PackageData;
import org.yzh.framework.session.Session;

public class Logger {

private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TCPServerHandler.class.getSimpleName());

public String logMessage(String type, PackageData packageData, String message) {
String log = type + " " + message;
logger.info(log);
return log;
}

public String logEvent(String event, Session session) {
String log = event + " " + session.getTerminalId();
logger.info(log);
return log;
}
}
6 changes: 4 additions & 2 deletions src/main/java/org/yzh/framework/mapping/Handler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.yzh.framework.mapping;

import org.yzh.framework.message.PackageData;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

Expand All @@ -20,8 +22,8 @@ public Handler(Object targetObject, Method actionMethod) {
this.targetMethod = actionMethod;
}

public Object invoke(Object... args) throws InvocationTargetException, IllegalAccessException {
return targetMethod.invoke(targetObject, args);
public <T extends PackageData> T invoke(Object... args) throws InvocationTargetException, IllegalAccessException {
return (T) targetMethod.invoke(targetObject, args);
}

public Class<?>[] getTargetParameterTypes() {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/yzh/framework/message/AbstractHeader.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public abstract class AbstractHeader {
*/
public abstract Integer getBodyLength();

public abstract void setBodyLength(Integer bodyLength);

@Override
public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/yzh/web/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.socket.config.annotation.EnableWebSocket;

@EnableWebSocket
@SpringBootApplication
public class Application {

Expand Down
19 changes: 19 additions & 0 deletions src/main/java/org/yzh/web/component/WebLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.yzh.web.component;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.yzh.framework.log.Logger;
import org.yzh.framework.message.PackageData;

@Component
public class WebLogger extends Logger {

@Autowired
WebSocketMessageHandler webSocketMessageHandler;

public String logMessage(String type, PackageData packageData, String message) {
String log = super.logMessage(type, packageData, message);
webSocketMessageHandler.broadcast(log);
return log;
}
}
38 changes: 38 additions & 0 deletions src/main/java/org/yzh/web/component/WebSocketInterceptor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.yzh.web.component;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.yzh.web.config.SessionKey;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;

public class WebSocketInterceptor implements HandshakeInterceptor {

@Autowired
private WebSocketMessageHandler webSocketMessageHandler;

@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
if (request instanceof ServletServerHttpRequest) {
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
HttpSession session = servletRequest.getSession();
Integer id = (Integer) session.getAttribute(SessionKey.USER_ID);
if (id != null) {
webSocketMessageHandler.closeSession(id);
attributes.put(SessionKey.USER_ID, id);
return true;
}
}
return false;
}

@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}
74 changes: 74 additions & 0 deletions src/main/java/org/yzh/web/component/WebSocketMessageHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.yzh.web.component;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.yzh.web.config.SessionKey;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebSocketMessageHandler extends TextWebSocketHandler {

private static final Map<Integer, WebSocketSession> webSocketMap = new ConcurrentHashMap();

public void closeSession(Integer id) {
WebSocketSession socketSession = webSocketMap.get(id);
if (socketSession != null) {
try {
socketSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 消息广播
*/
public void broadcast(String message) {
for (WebSocketSession socketSession : webSocketMap.values()) {
send(socketSession, message);
}
}

public void send(WebSocketSession socketSession, String message) {
try {
socketSession.sendMessage(new TextMessage(message));
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void afterConnectionEstablished(WebSocketSession session) {
Integer id = (Integer) session.getAttributes().get(SessionKey.USER_ID);
webSocketMap.put(id, session);
}

@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
if (message.getPayloadLength() < 1)
return;
for (WebSocketSession socketSession : webSocketMap.values())
socketSession.sendMessage(message);
}

@Override
public void handleTransportError(WebSocketSession session, Throwable error) {
error.printStackTrace();
}

@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
Integer id = (Integer) session.getAttributes().get(SessionKey.USER_ID);
webSocketMap.remove(id);
}

@Override
public boolean supportsPartialMessages() {
return false;
}
}
5 changes: 3 additions & 2 deletions src/main/java/org/yzh/web/config/NettyConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
import org.yzh.framework.codec.MessageEncoder;
import org.yzh.framework.mapping.HandlerMapper;
import org.yzh.framework.spring.SpringHandlerMapper;
import org.yzh.web.component.WebLogger;
import org.yzh.web.jt808.codec.JT808MessageDecoder;
import org.yzh.web.jt808.codec.JT808MessageEncoder;

@Configuration
public class NettyConfig {

@Bean
public TCPServer TCPServer() {
TCPServer server = new TCPServer(7611, (byte) 0x7e, handlerMapper(), messageDecoder(), messageEncoder());
public TCPServer TCPServer(WebLogger webLogger) {
TCPServer server = new TCPServer(7611, (byte) 0x7e, handlerMapper(), messageDecoder(), messageEncoder(), webLogger);
server.startServer();
return server;
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/yzh/web/config/SessionKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.yzh.web.config;

public interface SessionKey {

String USER = "user";
String USER_ID = "userId";

}
Loading

0 comments on commit 2050b67

Please sign in to comment.