진행도(프로그레스) 처리 전송 함수 추가

main
이범준 4 months ago
parent e813f051b0
commit dd8ea77f4b

@ -57,6 +57,18 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>3rd-party</groupId>
<artifactId>echelon</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>3rd-party</groupId>
<artifactId>dguard</artifactId>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

@ -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);
}
}
}
}

@ -12,6 +12,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import cokr.xit.base.code.CommonCode; import cokr.xit.base.code.CommonCode;
import cokr.xit.base.code.service.CodeService; import cokr.xit.base.code.service.CodeService;
@ -21,6 +22,7 @@ import cokr.xit.base.user.service.SigunguDepartmentService;
import cokr.xit.base.user.service.UserService; import cokr.xit.base.user.service.UserService;
import cokr.xit.fims.base.FimsUser; import cokr.xit.fims.base.FimsUser;
import cokr.xit.fims.base.service.bean.OgdpBean; import cokr.xit.fims.base.service.bean.OgdpBean;
import cokr.xit.fims.base.service.bean.SseBean;
import cokr.xit.fims.cmmn.CmmnUtil; import cokr.xit.fims.cmmn.CmmnUtil;
import cokr.xit.fims.task.TaskRequestMappingHandlerMapping; import cokr.xit.fims.task.TaskRequestMappingHandlerMapping;
import cokr.xit.foundation.data.DataObject; import cokr.xit.foundation.data.DataObject;
@ -38,6 +40,9 @@ public class MainController extends cokr.xit.base.web.MainController {
@Autowired @Autowired
private TaskRequestMappingHandlerMapping requestHandlers; private TaskRequestMappingHandlerMapping requestHandlers;
@Autowired
private SseBean sseBean;
@Resource(name="ogdpBean") @Resource(name="ogdpBean")
private OgdpBean ogdpBean; private OgdpBean ogdpBean;
@ -199,4 +204,11 @@ public class MainController extends cokr.xit.base.web.MainController {
.addObject("remoteAddr", remoteAddr) .addObject("remoteAddr", remoteAddr)
.addObject("net", net); .addObject("net", net);
} }
@RequestMapping(name="서버 이벤트 수신 등록", value="/subscribe.do")
public SseEmitter subscribe(HttpServletRequest req) {
return sseBean.start(req.getParameter("sseKey"));
}
} }

@ -6,6 +6,8 @@ public class CmmnQuery extends QueryRequest {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private String sseKey;
private String mainOption; private String mainOption;
private String subOption; private String subOption;
@ -31,6 +33,15 @@ public class CmmnQuery extends QueryRequest {
private String schRgtrCd; // 등록 사용자 코드 private String schRgtrCd; // 등록 사용자 코드
private String schRgtrNm; // 등록 사용자 명 private String schRgtrNm; // 등록 사용자 명
public String getSseKey() {
return ifEmpty(sseKey, () -> null);
}
public <T extends CmmnQuery> T setSseKey(String sseKey) {
this.sseKey = sseKey;
return self();
}
public String getMainOption() { public String getMainOption() {
return ifEmpty(mainOption, () -> null); return ifEmpty(mainOption, () -> null);
} }

@ -381,6 +381,9 @@ const GRID = {
} }
}; };
/**************************************************************************
* 엑셀다운로드시 개인정보 포함된 이름 정보 추출
**************************************************************************/
function getCellDefsForPrivacyCell($td_i){ function getCellDefsForPrivacyCell($td_i){
if($td_i.hasClass("privacy-cell")){ if($td_i.hasClass("privacy-cell")){
return $td_i.find("span:eq(0)").text(); return $td_i.find("span:eq(0)").text();
@ -388,3 +391,31 @@ function getCellDefsForPrivacyCell($td_i){
return $td_i.text(); return $td_i.text();
} }
} }
/**************************************************************************
* 프로그레스바 표시
**************************************************************************/
function fnProgress(sseKey, progressContent, progressEvent){
var eventSource = new EventSource(SSE_SUBSCRIBE_URL+"?sseKey="+sseKey);
eventSource.onopen = function(e) {
$.blockUI({
message : "<span id='progress-"+sseKey+"' >"+progressContent+"</span>",
css: { backgroundColor: "lightgrey", padding : "10px" }
});
};
eventSource.onerror = function(e) {
$.unblockUI();
};
eventSource.onmessage = function(e) {
if (e.data == 'FIN'){
eventSource.close();
$.unblockUI();
} else {
progressEvent(e.data);
}
};
}
Loading…
Cancel
Save