TCP 대응답 기능 추가

This commit is contained in:
hsoh
2022-07-01 19:46:42 +09:00
parent dc68e1de84
commit a82d7c4456
10 changed files with 634 additions and 191 deletions
+2 -1
View File
@@ -23,8 +23,9 @@ dependencies {
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
// implementation 'com.github.darrachequesne:spring-data-jpa-datatables:5.1.0'
implementation 'org.apache.commons:commons-lang3:3.10'
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
implementation 'commons-io:commons-io:2.6'
implementation 'com.jayway.jsonpath:json-path:2.4.0'
implementation 'io.netty:netty-all:4.1.60.Final'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
@@ -0,0 +1,191 @@
package com.eactive.httpmockserver.socket;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Positive;
import javax.validation.constraints.PositiveOrZero;
@SuppressWarnings("serial")
@Entity
public class BytesMessageSpec implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Column(length = 100, nullable = false)
private String specName;
@Column(length = 1)
private String llFieldInclude;
@Column(length = 1)
private String llFieldLengthInclude;
@Positive
private Integer llFieldLength;
private Integer llFieldLengthAlpha;
@PositiveOrZero
private Integer llFieldOffset;
@Column(length = 20)
private String llFieldType;
@Column(length = 20)
private String encode;
@Positive
private Integer port;
@Positive
private Integer sleepSeconds;
@Column
@Lob
private String responseBody;
@Column(length = 1)
private String useYn;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "BYTE_MESSAGE_SPEC_ID")
@OrderBy("position")
private List<EchoReplaceString> EchoReplaceStringList;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSpecName() {
return specName;
}
public void setSpecName(String specName) {
this.specName = specName;
}
public String getLlFieldInclude() {
return llFieldInclude;
}
public void setLlFieldInclude(String llFieldInclude) {
this.llFieldInclude = llFieldInclude;
}
public String getLlFieldLengthInclude() {
return llFieldLengthInclude;
}
public void setLlFieldLengthInclude(String llFieldLengthInclude) {
this.llFieldLengthInclude = llFieldLengthInclude;
}
public Integer getLlFieldLength() {
return llFieldLength;
}
public void setLlFieldLength(Integer llFieldLength) {
this.llFieldLength = llFieldLength;
}
public Integer getLlFieldLengthAlpha() {
return llFieldLengthAlpha;
}
public void setLlFieldLengthAlpha(Integer llFieldLengthAlpha) {
this.llFieldLengthAlpha = llFieldLengthAlpha;
}
public Integer getLlFieldOffset() {
return llFieldOffset;
}
public void setLlFieldOffset(Integer llFieldOffset) {
this.llFieldOffset = llFieldOffset;
}
public String getLlFieldType() {
return llFieldType;
}
public void setLlFieldType(String llFieldType) {
this.llFieldType = llFieldType;
}
public String getEncode() {
return encode;
}
public void setEncode(String encode) {
this.encode = encode;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public Integer getSleepSeconds() {
return sleepSeconds;
}
public void setSleepSeconds(Integer sleepSeconds) {
this.sleepSeconds = sleepSeconds;
}
public String getResponseBody() {
return responseBody;
}
public void setResponseBody(String responseBody) {
this.responseBody = responseBody;
}
public String getUseYn() {
return useYn;
}
public void setUseYn(String useYn) {
this.useYn = useYn;
}
public List<EchoReplaceString> getEchoReplaceStringList() {
return EchoReplaceStringList;
}
public void setEchoReplaceStringList(List<EchoReplaceString> echoReplaceStringList) {
EchoReplaceStringList = echoReplaceStringList;
}
@Override
public String toString() {
return "BytesMessageSpec [id=" + id + ", specName=" + specName + ", llFieldInclude=" + llFieldInclude
+ ", llFieldLengthInclude=" + llFieldLengthInclude + ", llFieldLength=" + llFieldLength
+ ", llFieldLengthAlpha=" + llFieldLengthAlpha + ", llFieldOffset=" + llFieldOffset + ", llFieldType="
+ llFieldType + ", encode=" + encode + ", port=" + port + ", sleepSeconds=" + sleepSeconds
+ ", responseBody=" + responseBody + ", useYn=" + useYn + ", EchoReplaceStringList="
+ EchoReplaceStringList + "]";
}
}
@@ -0,0 +1,9 @@
package com.eactive.httpmockserver.socket;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BytesMessageSpecDao extends JpaRepository<BytesMessageSpec, Long> {
BytesMessageSpec findFirstByUseYn(String useYn);
}
@@ -0,0 +1,5 @@
package com.eactive.httpmockserver.socket;
public interface BytesMessageSpecService {
public BytesMessageSpec findActiveBytesMessageSpec();
}
@@ -0,0 +1,18 @@
package com.eactive.httpmockserver.socket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(propagation = Propagation.SUPPORTS)
public class BytesMessageSpecServiceImpl implements BytesMessageSpecService {
@Autowired
private BytesMessageSpecDao dao;
@Override
public BytesMessageSpec findActiveBytesMessageSpec() {
return dao.findFirstByUseYn("Y");
}
}
@@ -0,0 +1,57 @@
package com.eactive.httpmockserver.socket;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.PositiveOrZero;
@SuppressWarnings("serial")
@Entity
public class EchoReplaceString implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@PositiveOrZero
@Column(nullable = false)
private Integer position;
@NotBlank
@Column(length = 5000, nullable = false)
private String replaceString;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
public String getReplaceString() {
return replaceString;
}
public void setReplaceString(String replaceString) {
this.replaceString = replaceString;
}
@Override
public String toString() {
return "EchoReplaceString [id=" + id + ", position=" + position + ", replaceString=" + replaceString + "]";
}
}
@@ -1,73 +1,84 @@
//package com.eactive.httpmockserver.socket;
//
//import java.nio.ByteOrder;
//
//import javax.annotation.PreDestroy;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.stereotype.Component;
//
//import io.netty.bootstrap.ServerBootstrap;
//import io.netty.channel.Channel;
//import io.netty.channel.ChannelFuture;
//import io.netty.channel.ChannelInitializer;
//import io.netty.channel.ChannelOption;
//import io.netty.channel.ChannelPipeline;
//import io.netty.channel.EventLoopGroup;
//import io.netty.channel.nio.NioEventLoopGroup;
//import io.netty.channel.socket.SocketChannel;
//import io.netty.channel.socket.nio.NioServerSocketChannel;
//import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
//import io.netty.handler.codec.LengthFieldPrepender;
//import io.netty.handler.codec.string.StringDecoder;
//import io.netty.util.CharsetUtil;
//
//@Component
//public class EchoSocketServer {
// private final Logger logger = LoggerFactory.getLogger(this.getClass());
//
// private Channel channel;
//
// public void start() {
// EventLoopGroup bossGroup = new NioEventLoopGroup();
// EventLoopGroup workerGroup = new NioEventLoopGroup();
// try {
// ServerBootstrap server = new ServerBootstrap();
// // @formatter:off
// server.group(bossGroup, workerGroup)
// .channel(NioServerSocketChannel.class)
// .childHandler(new ChannelInitializer<SocketChannel>() {
// @Override
// protected void initChannel(SocketChannel ch) throws Exception {
// ChannelPipeline pipeline = ch.pipeline();
// //pipeline.addLast(new LengthFieldBasedFrameDecoder (ByteOrder.LITTLE_ENDIAN,Integer.MAX_VALUE,0,8,0,8,true));
// //pipeline.addLast(new LengthFieldPrepender(8));
// //pipeline.addLast(new LengthFieldBasedFrameDecoder (Integer.MAX_VALUE,0,8,0,8));
// //pipeline.addLast(new LengthFieldBasedFrameDecoder (Integer.MAX_VALUE,0,2,0,2));
// //pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
// pipeline.addLast(new EchoSocketServerHandler());
// }
// })
// .option(ChannelOption.SO_BACKLOG, 128)
// .childOption(ChannelOption.SO_KEEPALIVE, false);
// // @formatter:on
//
// ChannelFuture channelFuture = server.bind(28181).sync();
// channel = channelFuture.channel().closeFuture().sync().channel();
// } catch (Exception e) {
// logger.error(e.getMessage());
// } finally {
// bossGroup.shutdownGracefully();
// workerGroup.shutdownGracefully();
// }
// }
//
// @PreDestroy
// public void stop() {
// if (channel != null) {
// channel.close();
// channel.parent().closeFuture();
// }
// }
//}
package com.eactive.httpmockserver.socket;
import javax.annotation.PreDestroy;
import javax.persistence.NoResultException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
@Component
public class EchoSocketServer {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private BytesMessageSpec spec;
EventLoopGroup bossGroup;
EventLoopGroup workerGroup;
ChannelFuture channelFuture;
public EchoSocketServer() {
}
public EchoSocketServer(BytesMessageSpec spec) {
this.spec = spec;
}
public void start() throws Exception {
if (spec == null) {
throw new NoResultException();
}
int port = (spec.getPort() == null ? 38181 : spec.getPort().intValue());
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap server = new ServerBootstrap();
// @formatter:off
server.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LengthHeaderFrameDecoder(spec));
pipeline.addLast(new EchoSocketServerHandler(spec));
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, false);
// @formatter:on
channelFuture = server.bind(port).sync();
channelFuture.channel().closeFuture().sync().channel();
logger.info(port + " port bounded");
} catch (Exception e) {
logger.error(e.getMessage());
throw e;
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
@PreDestroy
public void stop() {
try {
bossGroup.shutdownGracefully().sync();
workerGroup.shutdownGracefully().sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@@ -1,72 +1,144 @@
//package com.eactive.httpmockserver.socket;
//
//import java.nio.charset.StandardCharsets;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.stereotype.Component;
//
//import io.netty.buffer.ByteBuf;
//import io.netty.channel.ChannelHandler.Sharable;
//import io.netty.channel.ChannelHandlerContext;
//import io.netty.channel.ChannelInboundHandlerAdapter;
//
//@Component
//@Sharable
//public class EchoSocketServerHandler extends ChannelInboundHandlerAdapter {
// private final Logger logger = LoggerFactory.getLogger(this.getClass());
//
// private int DATA_LENGTH = 2048;
// private ByteBuf buff;
//
// @Override
// public void handlerAdded(ChannelHandlerContext ctx) {
// logger.info("EchoSocketServer handlerAdded");
// buff = ctx.alloc().buffer(DATA_LENGTH);
// }
//
// @Override
// public void channelActive(ChannelHandlerContext ctx) {
// logger.info("Remote Address: " + ctx.channel().remoteAddress().toString());
// }
//
// @Override
// public void channelRead(ChannelHandlerContext ctx, Object msg) {
// logger.info("EchoSocketServer channelRead");
//// ByteBuf buf = (ByteBuf) msg;
//// byte[] bytes = new byte[buf.readableBytes()];
//// buf.readBytes(bytes);
//// String data = new String(bytes, StandardCharsets.UTF_8);
//
//// ByteBuf mBuf = (ByteBuf) msg;
//// buff.writeBytes(mBuf); // 클라이언트에서 보내는 데이터가 축적됨
//// mBuf.release();
////
//// //final ChannelFuture f = ctx.writeAndFlush(buff);
////
//// System.out.println("TcpServer: " + buff.toString());
//// ctx.writeAndFlush(buff);
//
// String message = ((ByteBuf) msg).toString();
// System.out.println("message=" + message);
// ctx.write(msg);
// }
//
// @Override
// public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// logger.info("EchoSocketServer channelReadComplete");
// ctx.flush();
// }
//
// @Override
// public void handlerRemoved(ChannelHandlerContext ctx) {
// logger.info("EchoSocketServer handlerRemoved");
// buff = null;
// }
//
// @Override
// public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// ctx.close();
// cause.printStackTrace();
// }
//}
package com.eactive.httpmockserver.socket;
import java.io.UnsupportedEncodingException;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
@Component
@Sharable
public class EchoSocketServerHandler extends ChannelInboundHandlerAdapter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private BytesMessageSpec spec;
public EchoSocketServerHandler() {
}
public EchoSocketServerHandler(BytesMessageSpec spec) {
this.spec = spec;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
logger.info("EchoSocketServer handlerAdded");
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
logger.info("Remote Address: " + ctx.channel().remoteAddress().toString());
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
logger.info("EchoSocketServer channelRead");
try {
spec.setEncode(StringUtils.defaultIfBlank(spec.getEncode(), "euc-kr"));
String message = new String(ByteBufUtil.getBytes((ByteBuf) msg), spec.getEncode());
logger.info("==================================================");
logger.info("Received Message=" + message);
logger.info("==================================================");
// length + content
String responseMsg = assignResponseMessage(message);
logger.info("==================================================");
logger.info("Response Message=" + responseMsg);
logger.info("==================================================");
// sleep Àû¿ë
if (spec.getSleepSeconds() != null) {
int sleepSeconds = spec.getSleepSeconds().intValue();
if (sleepSeconds > 0) {
logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
logger.info("Start Sleep {} Seconds.", sleepSeconds);
logger.info("...");
Thread.sleep(sleepSeconds * 1000l);
logger.info("......");
logger.info("Finished Sleep {} Seconds.", sleepSeconds);
logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
}
ctx.write(Unpooled.wrappedBuffer(responseMsg.getBytes(spec.getEncode())));
} catch (Exception e) {
logger.error(e.getMessage());
}
}
private String assignResponseMessage(String body) throws UnsupportedEncodingException {
int llFieldLength = (spec.getLlFieldLength() == null ? 8 : spec.getLlFieldLength().intValue());
if (StringUtils.isNotBlank(spec.getResponseBody())) {
return appendLengthField(StringUtils.substring(spec.getResponseBody(), llFieldLength), spec);
}
if (spec.getEchoReplaceStringList() != null) {
byte[] bytes = body.getBytes(spec.getEncode());
for (EchoReplaceString echoReplaceString : spec.getEchoReplaceStringList()) {
bytes = replaceString(bytes, echoReplaceString.getPosition().intValue(),
echoReplaceString.getReplaceString().getBytes(spec.getEncode()), llFieldLength);
}
body = new String(bytes, spec.getEncode());
}
return appendLengthField(body, spec);
}
private byte[] replaceString(byte[] bytes, int position, byte[] replaceBytes, int llFieldLength) {
int idx = position - llFieldLength;
if (idx < 0 || bytes.length < idx) {
logger.warn("//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**");
logger.warn("//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**");
logger.warn("invalid postion(MessageSize={}, postion={})", bytes.length + llFieldLength, position);
return bytes;
}
if (bytes.length < idx + replaceBytes.length) {
byte[] newBytes = new byte[idx + replaceBytes.length];
System.arraycopy(bytes, 0, newBytes, 0, idx);
System.arraycopy(replaceBytes, 0, newBytes, idx, replaceBytes.length);
return newBytes;
}
System.arraycopy(replaceBytes, 0, bytes, idx, replaceBytes.length);
return bytes;
}
public static String appendLengthField(String body, BytesMessageSpec spec) throws UnsupportedEncodingException {
int llFieldLength = (spec.getLlFieldLength() == null ? 8 : spec.getLlFieldLength().intValue());
int length = body.getBytes(spec.getEncode()).length;
if (BooleanUtils.toBoolean(spec.getLlFieldLengthInclude())) {
length += llFieldLength;
}
return String.format("%0" + llFieldLength + "d%s", length, body);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
logger.info("EchoSocketServer channelReadComplete");
ctx.flush();
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
logger.info("EchoSocketServer handlerRemoved");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
ctx.close();
cause.printStackTrace();
}
}
@@ -0,0 +1,55 @@
package com.eactive.httpmockserver.socket;
import java.util.List;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
public class LengthHeaderFrameDecoder extends ReplayingDecoder<Void> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private boolean readLength;
private int length;
private BytesMessageSpec spec;
public LengthHeaderFrameDecoder() {
}
public LengthHeaderFrameDecoder(BytesMessageSpec spec) {
this.spec = spec;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> out) throws Exception {
int llFieldLength = (spec.getLlFieldLength() == null ? 8 : spec.getLlFieldLength().intValue());
if (!readLength) {
ByteBuf lengthFrame = buf.readBytes(llFieldLength);
length = assignMessageLength(ByteBufUtil.getBytes(lengthFrame));
readLength = true;
logger.info("MessageLength = " + length);
checkpoint();
}
if (readLength) {
int contentLength = (BooleanUtils.toBoolean(spec.getLlFieldLengthInclude()) ? length - llFieldLength
: length);
ByteBuf frame = buf.readBytes(contentLength);
readLength = false;
checkpoint();
out.add(frame);
}
}
private int assignMessageLength(byte[] bytes) {
String lengthStr = new String(bytes);
return NumberUtils.toInt(lengthStr);
}
}
@@ -1,45 +1,69 @@
//package com.eactive.httpmockserver.socket;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Controller;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.ResponseBody;
//
//@Controller
//public class SocketServerManageController {
// private final Logger logger = LoggerFactory.getLogger(this.getClass());
//
// @Autowired
// private EchoSocketServer echoSocketServer;
//
// @RequestMapping("/manage/socket/startEchoSocketServer")
// @ResponseBody
// public String startEchoServer() {
// logger.info("starting..");
//
// new Thread(new Runnable() {
// @Override
// public void run() {
// try {
// echoSocketServer.start();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// }).start();
//
// logger.info("started");
// return "Success";
// }
//
// @RequestMapping("/manage/socket/stopEchoSocketServer")
// @ResponseBody
// public String stopEchoServer() {
// logger.info("stopping..");
// echoSocketServer.stop();
// logger.info("stopped");
// return "Success";
// }
//}
package com.eactive.httpmockserver.socket;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.persistence.NoResultException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SocketServerManageController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private BytesMessageSpecService specService;
private EchoSocketServer echoSocketServer;
@PostConstruct
public void start() {
logger.info("EchoSocketServer starting..");
BytesMessageSpec spec = specService.findActiveBytesMessageSpec();
if (spec == null) {
logger.info("EchoSocketServer not started(No have rule)");
return;
}
logger.info("BytesMessageSpec=" + spec.toString());
new Thread(new Runnable() {
@Override
public void run() {
try {
echoSocketServer = new EchoSocketServer(spec);
echoSocketServer.start();
logger.info("EchoSocketServer started");
} catch (NoResultException e) {
logger.info("EchoSocketServer not started(No have rule)");
} catch (Exception e) {
logger.error(e.getMessage());
}
}
}).start();
}
@PreDestroy
public void stop() {
logger.info("EchoSocketServer stopping..");
if (echoSocketServer != null) {
echoSocketServer.stop();
}
logger.info("EchoSocketServer stopped");
}
@RequestMapping("/manage/socket/restartEchoSocketServer")
@ResponseBody
public String restartEchoServer() {
stop();
start();
return "Success";
}
}