진행도(프로그레스) 처리 전송 함수 추가
parent
e813f051b0
commit
dd8ea77f4b
@ -0,0 +1,25 @@
|
|||||||
|
package cokr.xit.fims.base;
|
||||||
|
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
|
import cokr.xit.foundation.data.DataObject;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class SseEntity {
|
||||||
|
|
||||||
|
private long createdAt;
|
||||||
|
|
||||||
|
private SseEmitter emitter;
|
||||||
|
|
||||||
|
private DataObject progress;
|
||||||
|
|
||||||
|
public SseEntity(SseEmitter emitter) {
|
||||||
|
this.createdAt = System.currentTimeMillis();
|
||||||
|
this.emitter = emitter;
|
||||||
|
this.progress = new DataObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,189 @@
|
|||||||
|
package cokr.xit.fims.base.service.bean;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.apache.catalina.connector.ClientAbortException;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import cokr.xit.fims.base.SseEntity;
|
||||||
|
import cokr.xit.foundation.component.AbstractBean;
|
||||||
|
|
||||||
|
@Component("sseBean")
|
||||||
|
public class SseBean extends AbstractBean {
|
||||||
|
private static final long ONE_HOUR = 60 * 1000;
|
||||||
|
private String cursor;
|
||||||
|
private ConcurrentHashMap<String, SseEntity> sseMap = new ConcurrentHashMap<>();
|
||||||
|
private static final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||||
|
|
||||||
|
|
||||||
|
@Resource(name="objectMapper")
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
/** SSE키를 등록한다.
|
||||||
|
* @param sseKey
|
||||||
|
* @return SseEmitter
|
||||||
|
*/
|
||||||
|
public SseEmitter start(String sseKey) {
|
||||||
|
SseEmitter emitter = new SseEmitter(-1L);
|
||||||
|
sseMap.put(sseKey, new SseEntity(emitter));
|
||||||
|
return emitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 작업할 SSE키를 설정한다.
|
||||||
|
* @param sseKey
|
||||||
|
* @return SseBean
|
||||||
|
*/
|
||||||
|
public SseBean setCursor(String sseKey) {
|
||||||
|
this.cursor = sseKey;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 클라이언트에 메시지를 전송한다.
|
||||||
|
* @param msg 메시지
|
||||||
|
* @return SseBean
|
||||||
|
*/
|
||||||
|
public void send(Object msg) {
|
||||||
|
if(ifEmpty(this.cursor, ()->"").equals("")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SseEntity se = sseMap.get(this.cursor);
|
||||||
|
if (se == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
se.getEmitter().send(msg);
|
||||||
|
} catch (ClientAbortException ex) {
|
||||||
|
if (se != null && se.getEmitter() != null) {
|
||||||
|
se.getEmitter().complete();
|
||||||
|
se.setEmitter(null);
|
||||||
|
sseMap.remove(this.cursor);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
if (se != null && se.getEmitter() != null) {
|
||||||
|
se.getEmitter().complete();
|
||||||
|
se.setEmitter(null);
|
||||||
|
sseMap.remove(this.cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 클라이언트에 종료 메시지를 전송한다.
|
||||||
|
* @param
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void end() {
|
||||||
|
if(ifEmpty(this.cursor, ()->"").equals("")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SseEntity se = sseMap.get(this.cursor);
|
||||||
|
if (se == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String msg = "FIN";
|
||||||
|
try {
|
||||||
|
se.getEmitter().send(msg);
|
||||||
|
} catch (ClientAbortException ex) {
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (se != null && se.getEmitter() != null) {
|
||||||
|
se.getEmitter().complete();
|
||||||
|
se.setEmitter(null);
|
||||||
|
sseMap.remove(this.cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(cron = "0 0 */1 * * *")
|
||||||
|
public void clearSseEmitter() {
|
||||||
|
long now = System.currentTimeMillis() - ONE_HOUR;
|
||||||
|
Iterator<String> it = sseMap.keys().asIterator();
|
||||||
|
System.out.println("size: "+sseMap.size());
|
||||||
|
while (it.hasNext()) {
|
||||||
|
String key = it.next();
|
||||||
|
System.out.println("key: "+key);
|
||||||
|
SseEntity se = sseMap.get(key);
|
||||||
|
if (now > se.getCreatedAt()) {
|
||||||
|
System.out.println("clear old ssemitter "+key+" : "+format.format(se.getCreatedAt()));
|
||||||
|
if (se.getEmitter() != null) {
|
||||||
|
se.setEmitter(null);
|
||||||
|
}
|
||||||
|
sseMap.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SseBean setProgress(String key, Object value) {
|
||||||
|
if(ifEmpty(this.cursor, ()->"").equals("")) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SseEntity se = sseMap.get(this.cursor);
|
||||||
|
se.getProgress().set(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SseBean increaseProgress(String key) {
|
||||||
|
if(ifEmpty(this.cursor, ()->"").equals("")) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SseEntity se = sseMap.get(this.cursor);
|
||||||
|
int i = se.getProgress().number(key).intValue();
|
||||||
|
se.getProgress().set(key, i+1);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SseBean increaseProgress(String key, int num) {
|
||||||
|
if(ifEmpty(this.cursor, ()->"").equals("")) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SseEntity se = sseMap.get(this.cursor);
|
||||||
|
int i = se.getProgress().number(key).intValue();
|
||||||
|
se.getProgress().set(key, i+num);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendProgress() {
|
||||||
|
if(ifEmpty(this.cursor, ()->"").equals("")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SseEntity se = sseMap.get(this.cursor);
|
||||||
|
if (se == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
se.getEmitter().send(objectMapper.writeValueAsString(se.getProgress()));
|
||||||
|
} catch (ClientAbortException ex) {
|
||||||
|
if (se != null && se.getEmitter() != null) {
|
||||||
|
se.getEmitter().complete();
|
||||||
|
se.setEmitter(null);
|
||||||
|
sseMap.remove(this.cursor);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
if (se != null && se.getEmitter() != null) {
|
||||||
|
se.getEmitter().complete();
|
||||||
|
se.setEmitter(null);
|
||||||
|
sseMap.remove(this.cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue