SpringMVC 비동기 처리 작업(Callable 과 Deferred Result)
10776 단어 SpringMVC비동기CallableDeferredResult
이렇게 하 는 장점 은 서비스 연결 탱크 를 오래 점용 하지 않 고 서버 의 스루풋 을 높이 는 것 이다.
Callable
@GetMapping("/callable")
public Callable<String> testCallable() throws InterruptedException {
log.info(" !");
Callable<String> result = new Callable<String>() {
@Override
public String call() throws Exception {
log.info(" !");
Thread.sleep(1000);
log.info(" !");
return "SUCCESS";
}
};
log.info(" !");
return result;
}
출력 결 과 는 다음 과 같 습 니 다.메 인 스 레 드 시작!
메 인 스 레 드 끝!
부 스 레 드 시작!
부 스 레 드 끝!
메 인 라인 은 미리 되 돌아 와 다른 요청 을 처리 할 수 있 으 며 결과 가 나 오 면 출력 할 수 있 습 니 다.
DeferredResult
비동기 요청 처리 기능 을 사용 하면 컨트롤 러 는 반환 값 을 Deferred Result 에 포장 할 수 있 고 컨트롤 러 는 서로 다른 스 레 드 비동기 에서 반환 값 을 만 들 수 있 습 니 다.장점 은 전혀 상 관 없 는 두 라인 간 의 통신 을 실현 할 수 있다 는 것 이다.우 리 는 다음 과 같은 장면 을 모 의 한다.
메시지 큐 와 응용 2 부분 이 너무 번 거 로 워 서,우 리 는 하나의 종 류 를 사용 하여 대체 합 니 다.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class MockQueue {
private String placeOrder;
private String completeOrder;
private Logger logger = LoggerFactory.getLogger(getClass());
public String getPlaceOrder() {
return placeOrder;
}
public void setPlaceOrder(String placeOrder) throws Exception {
new Thread(() -> {
logger.info(" , " + placeOrder);
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
this.completeOrder = placeOrder;
logger.info(" ," + placeOrder);
}).start();
}
public String getCompleteOrder() {
return completeOrder;
}
public void setCompleteOrder(String completeOrder) {
this.completeOrder = completeOrder;
}
}
컨트롤 러 즉 스 레 드 1 의 부분 을 정의 합 니 다.
import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
@RestController
public class AsyncController {
@Autowired
private MockQueue mockQueue;
@Autowired
private DeferredResultHolder deferredResultHolder;
private Logger logger = LoggerFactory.getLogger(getClass());
@RequestMapping("/order")
public DeferredResult<String> order() throws Exception {
logger.info(" ");
String orderNumber = RandomStringUtils.randomNumeric(8);
mockQueue.setPlaceOrder(orderNumber);
DeferredResult<String> result = new DeferredResult<>();
deferredResultHolder.getMap().put(orderNumber, result);
return result;
}
}
스 레 드 1 과 스 레 드 2 간 통신 을 위 한 클래스 를 정의 합 니 다.@Component 를 사용 하면 기본적으로 하나의 예 로 통신 이 편리 합 니 다.
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.DeferredResult;
@Component
public class DeferredResultHolder {
private Map<String, DeferredResult<String>> map = new HashMap<String, DeferredResult<String>>();
public Map<String, DeferredResult<String>> getMap() {
return map;
}
public void setMap(Map<String, DeferredResult<String>> map) {
this.map = map;
}
}
주문 서 를 감청 할 클래스 를 정의 합 니 다.처리 가 완료 되면 deferred ResultHolder 의 Deferred Result 값 을 설정 하면 결 과 를 되 돌려 줍 니 다.
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class QueueListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private MockQueue mockQueue;
@Autowired
private DeferredResultHolder deferredResultHolder;
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
new Thread(() -> {
while (true) {
if (StringUtils.isNotBlank(mockQueue.getCompleteOrder())) {
String orderNumber = mockQueue.getCompleteOrder();
logger.info(" :"+orderNumber);
deferredResultHolder.getMap().get(orderNumber).setResult("place order success");
mockQueue.setCompleteOrder(null);
}else{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
추가:springmvc 비동기 처리 요청 사용동기 화 요청 그림:
동기 화 처 리 된 그림 은 다음 과 같 습 니 다.HTTP 요청,tomcat 또는 다른 미들웨어 에 해당 하 는 스 레 드 가 있 습 니 다.이 Http 요청 을 처리 하고 모든 업무 논 리 는 이 스 레 드 에서 실 행 됩 니 다.마지막 으로 Http 응답 으로 돌아 갑 니 다.그러나 tomcat 등 미들웨어 는 관리 할 수 있 는 스 레 드 수가 제한 되 어 있 으 며,수량 이 어느 정도 에 이 르 면 다시 들 어 오 라 고 요청 하면 차단 된다.
간단 한 비동기 그림:
비동기 처리 과정:http 요청 이 들 어 오 면 tomcat 등 미들웨어 의 메 인 스 레 드 는 부 스 레 드 를 호출 하여 업무 논 리 를 수행 합 니 다.부 스 레 드 처리 가 완료 되면 메 인 스 레 드 는 결 과 를 되 돌려 줍 니 다.부 스 레 드 가 전체 업무 논 리 를 처리 하 는 과정 에서 메 인 스 레 드 는 남 은 채 로 다른 요청 을 합 니 다.즉,상기 모델 로 http 요청 을 처리 합 니 다.서버 의 스루풋 이 뚜렷하게 증가 할 것 이다.비동기 로 되 돌아 가 려 면 웹.xml 에서 version 을 3.0 버 전 으로 설정 해 야 합 니 다.
servlet 및 모든 filter 에 비동기 지원 을 설정 합 니 다.
간단하게 다음 과 같이 실현 합 니 다.
더욱 복잡 한 업무 장면 의 비동기 화 는 다음 과 같다.
Htpp 는 스 레 드 를 통 해 처리 하고 메 시 지 를 메시지 큐 에 보 내 달라 고 요청 합 니 다.2 는 서로 다른 서버 에 있 습 니 다.메 시 지 를 받 고 메 시 지 를 되 돌려 줍 니 다.스 레 드 2 는 처리 결 과 를 감청 하고 메 시 지 를 되 돌려 줍 니 다.스 레 드 1 과 스 레 드 2 는 상대방 의 존 재 를 모 릅 니 다.이러한 업무 상황 은 하나의 스 레 드 만 열 면 해결 할 수 없 으 며 Deferred Result 류 를 사용 해 야 합 니 다.
간단 한 실현 코드 는 다음 과 같다.
controller 계층:
@Controller
@RequestMapping("/test/")
@Slf4j
public class TestController {
@Autowired
private MockQueue mockQueue;
@Autowired
private DeferredResultHolder deferredResultHolder;
@RequestMapping("order")
@ResponseBody
public DeferredResult<String> test() throws InterruptedException {
log.info(" ");
String orderNo = RandomUtils.nextInt() + "";
mockQueue.setPlaceOrder(orderNo);
DeferredResult<String> result = new DeferredResult<String>();
deferredResultHolder.getMap().put(orderNo, result);
log.info(" ");
return result;
}
}
의사 메시지 큐 클래스:
@Slf4j
@Component
public class MockQueue {
private String placeOrder;
private String compeleteOrder;
public String getPlaceOrder() {
return placeOrder;
}
public void setPlaceOrder(String placeOrder) throws InterruptedException {
new Thread(()->{ log.info(" ");
this.placeOrder = placeOrder;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.compeleteOrder = placeOrder;
log.info(" ");}).start();
}
public String getCompeleteOrder() {
return compeleteOrder;
}
public void setCompeleteOrder(String compeleteOrder) {
this.compeleteOrder = compeleteOrder;
}
}
위조 대기 열 감청 클래스:
@Slf4j
@Component
public class QueueListener implements ApplicationListener{
@Autowired
private MockQueue mockQueue;
@Autowired
private DeferredResultHolder deferredResultHolder;
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
new Thread(() ->{
while (true){
if(StringUtils.isNotBlank(mockQueue.getCompeleteOrder())){
String orderNum = mockQueue.getCompeleteOrder();
log.info(" " + orderNum);
deferredResultHolder.getMap().get(orderNum).setResult("success");
mockQueue.setCompeleteOrder(null);
}else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
용기 종류:
@Component
public class DeferredResultHolder {
private Map<String,DeferredResult<String>> map = new HashMap<String,DeferredResult<String>>();
public Map<String, DeferredResult<String>> getMap() {
return map;
}
public void setMap(Map<String, DeferredResult<String>> map) {
this.map = map;
}
}
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.만약 잘못 이 있 거나 완전히 고려 하지 않 은 부분 이 있다 면 아낌없이 가르침 을 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
ssm 프레임워크 업로드 이미지 로컬 및 데이터베이스에 저장 예시본고는 ssm 프레임워크 업로드 이미지를 로컬과 데이터베이스에 저장하는 예시를 소개하고 주로 Spring+SpringMVC+MyBatis 프레임워크를 사용하여 ssm 프레임워크 업로드 이미지의 실례를 실현했다. 구체...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.