首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Servlet 中應用裝飾模式增強 Request 對象

     編輯:Java 相關知識

問題背景

Servlet Filter 提供了強大的攔截機制,可在請求到達 Servlet 前後處理 HttpServletRequest/HttpServletResponse。但 HttpServletRequest 的參數 Map 是不可修改的,這限制了 Filter 的應用場景——例如想在 Struts Action 前自動去除用戶輸入的多餘空格,卻無法直接修改請求參數。

裝飾模式原理

裝飾模式通過組合而非繼承動態擴展對象功能。核心角色:

  • Component:定義接口(如 ServletRequest)
  • ConcreteComponent:容器生成的實現類(如 HttpServletRequestImpl)
  • Decorator:實現同一接口,持有 Component 引用,轉發調用並在需要處攔截修改

Servlet API 內置支援

Servlet 規範已提供 ServletRequestWrapper / HttpServletRequestWrapper 作為裝飾基類,開發者只需繼承並覆寫目標方法:

public class TrimRequestWrapper extends HttpServletRequestWrapper {
    public TrimRequestWrapper(HttpServletRequest request) { super(request); }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        return value == null ? null : value.trim();
    }

    @Override
    public Map getParameterMap() {
        Map original = super.getParameterMap();
        Map trimmed = new HashMap<>();
        original.forEach((k, v) -> {
            String[] arr = Arrays.stream(v).map(String::trim).toArray(String[]::new);
            trimmed.put(k, arr);
        });
        return Collections.unmodifiableMap(trimmed);
    }
    // 同理覆寫 getParameterValues、getParameterNames 等
}

Filter 中應用裝飾器

public class TrimFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        chain.doFilter(new TrimRequestWrapper(request), resp);
    }
    // init/destroy 省略
}

在 web.xml 配置 Filter 即可全局生效,所有後續 Servlet/Filter/Struts Action 獲取到的參數均已去除首尾空白。

知名框架應用案例

  • Struts:org.apache.struts.upload.MultipartRequestWrapper 覆寫參數獲取方法實現文件上傳解析。
  • Apache Beehive:PageFlowRequestWrapper 增強請求處理能力。
  • Spring Security:SecurityContextHolderAwareRequestWrapper 注入安全上下文信息。

完整示例:去除空白字符 Filter

public class XssTrimFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (request instanceof HttpServletRequest) {
            chain.doFilter(new XssTrimWrapper((HttpServletRequest) request), response);
        } else {
            chain.doFilter(request, response);
        }
    }
}

class XssTrimWrapper extends HttpServletRequestWrapper {
    public XssTrimWrapper(HttpServletRequest request) { super(request); }

    private String clean(String input) {
        return input == null ? null : input.trim().replaceAll("[\\r\\n\\t]", "");
    }

    @Override public String getParameter(String name) { return clean(super.getParameter(name)); }
    @Override public String[] getParameterValues(String name) {
        String[] vals = super.getParameterValues(name);
        return vals == null ? null : Arrays.stream(vals).map(this::clean).toArray(String[]::new);
    }
    @Override public Map getParameterMap() {
        return super.getParameterMap().entrySet().stream()
            .collect(Collectors.toMap(Map.Entry::getKey, e -> Arrays.stream(e.getValue()).map(this::clean).toArray(String[]::new)));
    }
}

總結

裝飾模式完美解決了「無法修改容器創建的不可變對象」的難題。通過 HttpServletRequestWrapper,我們可以在不侵入業務代碼的前提下,實現參數清洗、XSS 防護、編碼轉換、國際化等橫切關注點,是 Servlet 開發中極具實戰價值的設計模式應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved