使用HttpServletResponse實現curl接口時控制檯輸出(續)

上一篇文章的問題

在上一篇文章 Spring Boot RestController接口如何輸出到終端 中討論瞭如何使用 HttpSerlvetResponse 寫入輸出流,使應急接口通過 curl 調用時可以在控制檯輸出信息,使運維人員知道命令執行情況。

但是上一篇文章的問題是,HttpServletResponse 是 Controller 的參數,這就使得如果要在其調用的 Service 方法中也要實現控制檯輸出,就必須讓所有涉及到的 Service 方法都帶上 HttpServletResponse 參數,這對業務的侵入實在太大,對於實際業務可能包含多個 Service、Component 之間的相互引用,改造成本是不可容忍的。

本文的解決思路

那麼筆者就在想,如何構造一個全局的 HttpServletResponse 對象,使它能夠在各個 Controller、Service、Component 之前傳遞呢?經過查閱資料發現,HttpServletResponse 對象本身是可以被 @Autowired@Resource 註解注入的!那麼我們就可以構造一個帶有自動注入的 HttpServletResponse 對象的 Component,然後在其他所有需要使用的地方去自動注入這個 Component 即可。

代碼

代碼實現如下:

@Component
public class WebUtil {
    @Resource
    private HttpServletResponse httpServletResponse;

    public void output(String message) {
        if (httpServletResponse == null) {
            return;
        }
        try {
            httpServletResponse.setContentType("text/plain;charset=utf-8");
            httpServletResponse.setCharacterEncoding("UTF-8");
            PrintWriter writer = httpServletResponse.getWriter();
            writer.println(message);
            writer.flush();
        } catch (Exception e) {
            return;
        }
    }
}

由於我們的目的只是爲了實現控制檯輸出,所以如果該方法拋出異常(主要是 IOExceptionIllegalStatesException),那麼直接返回即可。這個問題主要出在定時任務中,因爲定時任務是不含 HttpServletResponse 對象的,如果在定時任務中調用該方法的時候會拋出 IllegalStatesException

在要使用該方法的類中使用自動注入,注入 WebUtil 類,然後使用它的對象(而不是這個類本身)的output方法即可。

@Service
@Slf4j
public class TestServiceImpl implements TestService {
    @Resource
    private WebUtil webUtil;

    @Override
    public boolean emergencyOperation() throws IOException {
        log.info("開始執行應急操作任務");
        webUtil.output( "開始執行應急操作任務");
        for (int i = 0; i < 20; i++) {
            webUtil.output( "完成第" + (i+1) + "批次");
            log.info("完成第 {} 批次", i+1);
            try {
                Thread.sleep(500L);
            } catch (InterruptedException e) {
                log.warn("應急操作任務失敗");
                webUtil.output( "應急操作任務失敗");
                return false;
            }
        }
        log.info("完成應急操作任務");
        webUtil.output( "應急操作任務完成");
        return true;
    }
}

經過測試發現,curl調用接口可以實現控制檯輸出,定時任務也執行正常,沒有預期外的異常產生。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章