You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Struts2+Java7的前端波罗的海字符过滤通用方案选型咨询

针对波罗的海字符输入拦截的最优方案分析(Struts2 + Java7 + JSP-Servlet)

先直接给结论:优先选择基于HttpServlet Filter的全局请求参数遍历检查方案,它能同时适配Struts2和原生JSP-Servlet架构,实现成本低、复用性强,完全覆盖你的业务场景。下面详细对比两种思路,并补充其他可行方案:

一、两种思路的优劣对比

1. 反射遍历请求Bean对象(Struts2专属)

  • 优势:贴合Struts2的MVC模型,直接处理Action中封装的业务Bean,能针对复杂嵌套对象的属性做检查。
  • 劣势:
    • 只能覆盖Struts2场景,完全无法处理原生JSP-Servlet的请求参数,需要单独为Servlet写一套逻辑,维护成本翻倍。
    • 反射操作需要额外处理Bean的访问权限(比如私有属性的getter方法),如果系统中Bean没有统一的父类或注解标记,遍历所有属性容易误检内部业务字段。
    • 性能略低于直接遍历请求参数(反射的方法调用开销)。

2. 遍历HttpServlet请求参数(全局通用)

  • 优势:
    • 完美适配Struts2和JSP-Servlet两种架构:不管请求是被Struts2的核心Filter处理,还是直接交给Servlet,自定义Filter都能在请求到达业务逻辑前拦截检查。
    • 实现简单:直接通过request.getParameterMap()获取所有请求参数键值对,不需要关心后端的Bean结构,只需要检查参数值本身。
    • 可扩展性强:可以通过配置URL白名单(比如你提到的13个支持波罗的海字符的菜单),避免对合法请求做无效检查。
  • 劣势:
    • 如果存在POST提交的复杂JSON请求体(而非表单键值对),需要额外读取请求流并解析JSON后检查,但从你的场景描述看,应该以表单提交为主,这个问题影响不大。

二、最优方案的具体实现步骤

1. 编写自定义Filter

public class BalticCharFilter implements Filter {
    // 波罗的海字符正则匹配(包含所有需要拦截的字符)
    private static final String BALTIC_CHAR_PATTERN = "[ĀāČčĒēĢģĪīĶķĻļŅņŌōŠšŪūŽž]";
    // 白名单URL(13个支持波罗的海字符的菜单路径,可从配置文件读取)
    private Set<String> whiteListUrls;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化白名单,比如从web.xml的init-param读取
        String whiteListStr = filterConfig.getInitParameter("whiteListUrls");
        if (whiteListStr != null) {
            whiteListUrls = new HashSet<>(Arrays.asList(whiteListStr.split(",")));
        } else {
            whiteListUrls = new HashSet<>();
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 检查当前请求是否在白名单内,跳过检查
        String requestUrl = httpRequest.getRequestURI();
        if (whiteListUrls.stream().anyMatch(requestUrl::contains)) {
            chain.doFilter(request, response);
            return;
        }

        // 设置正确的字符集,避免参数乱码
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        // 遍历所有请求参数,检查波罗的海字符
        Map<String, String[]> paramMap = request.getParameterMap();
        boolean hasBalticChar = false;
        for (String[] values : paramMap.values()) {
            for (String value : values) {
                if (value != null && value.matches(".*" + BALTIC_CHAR_PATTERN + ".*")) {
                    hasBalticChar = true;
                    break;
                }
            }
            if (hasBalticChar) break;
        }

        if (hasBalticChar) {
            // 返回错误提示,比如跳转到错误页面或输出JSON提示
            httpResponse.sendRedirect(httpRequest.getContextPath() + "/error.jsp?msg=请不要输入波罗的海字符");
            // 如果是AJAX请求,可返回JSON:
            // response.setContentType("application/json");
            // response.getWriter().write("{\"code\":400,\"msg\":\"请不要输入波罗的海字符\"}");
            return;
        }

        // 无违规字符,继续执行请求
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理资源
    }
}

2. 配置Filter到web.xml

注意要把这个Filter放在Struts2核心Filter(org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter)之前,确保先执行参数检查:

<filter>
    <filter-name>BalticCharFilter</filter-name>
    <filter-class>com.yourcompany.filter.BalticCharFilter</filter-class>
    <init-param>
        <param-name>whiteListUrls</param-name>
        <param-value>/support/menu1,/support/menu2</param-value> <!-- 替换为你的13个菜单路径 -->
    </init-param>
</filter>
<filter-mapping>
    <filter-name>BalticCharFilter</filter-name>
    <url-pattern>/*</url-pattern> <!-- 拦截所有请求 -->
</filter-mapping>

<!-- 原有的Struts2 Filter -->
<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

三、其他补充方案(作为辅助)

1. 前端双重校验

在表单提交前用JavaScript检查输入内容,提前给用户提示,减少无效请求:

function checkBalticChar(input) {
    const pattern = /[ĀāČčĒēĢģĪīĶķĻļŅņŌōŠšŪūŽž]/;
    if (pattern.test(input.value)) {
        alert("请不要输入波罗的海字符");
        input.focus();
        return false;
    }
    return true;
}

注意:前端校验只能作为辅助,不能替代后端Filter,因为用户可以通过禁用JS或直接构造请求绕过前端检查。

2. Struts2拦截器(可选)

如果只针对Struts2场景做更精细的Bean检查,可以写自定义拦截器,结合OGNL或反射遍历Action的属性:

public class BalticCharInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
        // 遍历Action的属性(可通过反射或BeanUtils)
        BeanInfo beanInfo = Introspector.getBeanInfo(action.getClass());
        for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
            Method getter = pd.getReadMethod();
            if (getter != null) {
                Object value = getter.invoke(action);
                if (value instanceof String) {
                    String strValue = (String) value;
                    if (strValue.matches(".*[ĀāČčĒēĢģĪīĶķĻļŅņŌōŠšŪūŽž].*")) {
                        // 抛出异常或返回错误Result
                        return "input";
                    }
                }
            }
        }
        return invocation.invoke();
    }
}

然后在struts.xml中配置拦截器栈,应用到需要的Action上,但这种方案无法覆盖Servlet场景,所以还是Filter更通用。

总结

综合你的业务场景(两种架构并存、90个菜单需要统一处理),全局Filter方案是最优选择,它能一次性解决所有请求的参数检查问题,实现成本低、维护简单,且能和前端校验形成双重保障。

内容的提问来源于stack exchange,提问作者cFrags

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:31:28