ServletFilter, MDC

# ServletFilter
- Java EE の一部であり、セキュリティ、ロギング、圧縮などのサブレットレベルでの作業に適している。
- initとdestroyメソッドはdefault と作成しなくてもよい。
    ![스크린샷 2024-01-02 23.16.02 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567846/a0ae9a78-3b89-348e-3db3-59acefcd08ba.png)

- すべてのログを残す例
    ```java
    import lombok.extern.slf4j.Slf4j;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.UUID;
    
    @Slf4j
    public class LogFilter implements Filter { // Filter 인터페이스를 구현한다.
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            log.info("log filter init");
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            log.info("log filter doFilter");
    
            // Servlet Request はHTTP リクエストでない場合まで考慮して作ったインターフェースなので、
            // Http Servlet Request でダウンキャスティングすればよい。
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            String requestURI = httpServletRequest.getRequestURI();
    
            String uuid = UUID.randomUUID().toString();
    
            try {
                log.info("REQUEST [{}][{}]", uuid, requestURI);
                // 次のfilter呼び出し、なければservlet呼び出し
                chain.doFilter(request, response);
            } catch (Exception e) {
                throw e;
            } finally {
                log.info("RESPONSE [{}][{}]", uuid, requestURI);
            }
        }
    
        @Override
        public void destroy() {
            log.info("log filter destroy");
        }
    }
    
    
    2024-01-02 22:06:19.559 INFO  [restartedMain] [c.eunaa2934.acshop.web.filter.LogFilteƒr] - log filter init
    2024-01-02 22:06:22.184 INFO  [http-nio-8080-exec-8] [c.eunaa2934.acshop.web.filter.LogFilter] - REQUEST [0ea1e015-8728-494d-8d42-b928c27a1aba][/css/common/common.css]
    2024-01-02 22:06:22.184 INFO  [http-nio-8080-exec-9] [c.eunaa2934.acshop.web.filter.LogFilter] - REQUEST [f9a2e173-faf7-4ecd-96bd-e15b1eabcb02][/images/favicon.ico]
    2024-01-02 22:06:22.186 INFO  [http-nio-8080-exec-8] [c.eunaa2934.acshop.web.filter.LogFilter] - RESPONSE [0ea1e015-8728-494d-8d42-b928c27a1aba][/css/common/common.css]
    2024-01-02 22:06:22.186 INFO  [http-nio-8080-exec-9] [c.eunaa2934.acshop.web.filter.LogFilter] - RESPONSE [f9a2e173-faf7-4ecd-96bd-e15b1eabcb02][/images/favicon.ico]
    2024-01-02 22:15:47.525 INFO  [SpringApplicationShutdownHook] [c.eunaa2934.acshop.web.filter.LogFilter] - log filter destroy
    ```

# MDC
- Mapped Diagnostic Contexts
- Multiスレッドの場合のように、同時に要請が複数ある時、要請ごとに固有のIDを付与して区分できるように提供されるmapである。
- Thread Localに区別できるキー値を保存して、Threadが存在する間、引き続き使用できるようにする。
    ```properties
    application.properties
    logging.config=classpath:logback.xml
    ```
    ```xml
    詳しくはLogging参考
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration scan="true" scanPeriod="60 seconds">
        ...
    		<property name="LOG_PATTERN" value="[request_id=%X{request_id}] %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%logger{40}] - %msg%n"/>
    		...
    </configuration>
    ```
    ```java
    import org.slf4j.MDC;
    
    @Slf4j
    public class LogFilter implements Filter {
    
    		@Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            log.info("log filter doFilter");
    
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            String requestURI = httpServletRequest.getRequestURI();
    
            String uuid = UUID.randomUUID().toString();
    
            try {
                // request_id枠を通じて要請ごとに固有のIDを付与して区分できるようにする。
                MDC.put("request_id", uuid);
                log.info("REQUEST [{}]", requestURI);
                // 次のfilter呼び出し、なければservlet呼び出し
                chain.doFilter(request, response);
                // 要求が完了したときにクリアをしてくれないと、他の要求がそのスレッドを再利用するときに
                // 以前のデータが残っている可能性がある。
                MDC.clear();
            } catch (Exception e) {
                throw e;
            } finally {
                log.info("RESPONSE [{}]", requestURI);
            }
        }
    
    }
    
    // [request_id=75cbd951-7d1e-412b-adb8-66ebcf669c14] 2024-01-19 21:28:16.046 INFO  [http-nio-8080-exec-2] [c.eunaa2934.acshop.web.filter.LogFilter] - REQUEST [/images/favicon.ico]
    ```