如何外部化web.xml servlet的init-param? Spring DelegatingFilterProxy用于Servlet? - java

我有一个无法修改的第三方servlet。它接受我要外部化的init-param(来自web.xml)。

我可以使用DelegatingFilterProxy将servlet过滤器init-param外部化。这有效地将servlet过滤器定义移到Spring中,那里有更强大的外部化工具(例如:PropertyPlaceholderConfigurer,环境变量等)。

如何为servlet执行此操作?

参考方案

看起来您需要一个DelegatingServletProxy类,尽管它在Spring中并不存在。但是,我认为使用DelegatingFilterProxy作为起点,编写代码非常简单。

Servlet仅实现了一些具体方法,因此委托应该很简单。

好吧,我把钱放在嘴里!
编辑:下面是DelegatingServletProxy 的基本实现。

您可以这样使用它:

  • 在web.xml中设置通常的spring上下文配置/ ContextListener,以为webapp设置应用程序范围的spring上下文。
  • 向您的web.xml中添加一个servlet,其实现类为DelegatingServletProxy。这将替换您要更改其init-params的现有serlvet。您可以为此新的servlet设置初始化参数:proxyServletClass是servlet的类的名称。 proxyServletParams是您的spring配置中的Properties Bean的名称。此属性bean用于设置代理servlet的初始化参数。
  • 在您的spring配置中,添加一个新的Properites bean,它定义了init-params
  • 在Spring应用程序上下文中的一些示例

    <bean name="myInitParams" class="java.util.Properties">
       <constructor-arg>
       <props>
            <prop key="initParamName">initParamValue</prop>
       </props>
       </constructor-arg>
    </bean>
    

    web.xml片段示例

    <servlet>
       <servlet-name>...</servlet-name>
        <servlet-class>
            acme.DelegatingServletProxy
        </servlet-class>
        <init-param>
             <param-name>proxyServletClass</param-name>
             <param-value>your.original.servlet.ServletClass</param-value>
        </init-param>
        <init-param>
            <param-name>proxyServletParams</param-name>
            <param-value>myServletParams</param-value>
            <!-- name of bean in spring context -->
        </init-param>
    </servlet>
    

    这是servlet代码,虽然很长,但其中大多数是委派ServletContext-有趣的事情发生在顶部。它未经测试-应该视为起点。

    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.support.WebApplicationContextUtils;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServlet;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.Enumeration;
    import java.util.Properties;
    import java.util.Set;
    
    public class DelegatingServletProxy extends HttpServlet implements WebApplicationContextAware
    {
        private HttpServlet delegate;
    
        private Properties initParams;
        private String delegateName;
    
        public void setDelegateName(String delegateName)
        {
            this.delegateName = delegateName;
        }
    
        public void init(ServletConfig config) throws ServletException
        {
            super.init(config);
            WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
            delegate = wac.getBean(delegateName, HttpServlet.class);
            delegate.init(new WrapServletConfig(config));
        }
    
        @Override
        public void destroy()
        {
            delegate.destroy();
        }
    
        @Override
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
        {
            delegate.service(req, res);
        }
    
        public void setInitParams(Properties initParams)
        {
            this.initParams = initParams;
        }
    
        private class WrapServletConfig implements ServletConfig, ServletContext
        {
            // we override ServletContext also because it exposes getInitParameterNames()/getInitParemter()
            private ServletConfig delegate;
            private ServletContext delegateContext;
            public WrapServletConfig(ServletConfig config)
            {
                this.delegate = config;
                this.delegateContext = config.getServletContext();
            }
    
            @Override
            public String getServletName()
            {
                return delegate.getServletName();
            }
    
            @Override
            public ServletContext getServletContext()
            {
                return delegate.getServletContext();
            }
    
            @Override
            public String getInitParameter(String s)
            {
                return initParams.getProperty(s);
            }
    
            @Override
            public Enumeration getInitParameterNames()
            {
                return initParams.propertyNames();
            }
    
            @Override
            public Object getAttribute(String s)
            {
                return delegateContext.getAttribute(s);
            }
    
            @Override
            public Enumeration getAttributeNames()
            {
                return delegateContext.getAttributeNames();
            }
    
            @Override
            public void setAttribute(String s, Object o)
            {
                delegateContext.setAttribute(s, o);
            }
    
            @Override
            public void removeAttribute(String s)
            {
                delegateContext.removeAttribute(s);
            }
    
            @Override
            public String getServletContextName()
            {
                return delegateContext.getServletContextName();
            }
    
            // the remainer is just straight delegation to ServletContext
    
            @Override
            public ServletContext getContext(String s)
            {
                return delegateContext.getContext(s);
            }
    
            @Override
            public int getMajorVersion()
            {
                return delegateContext.getMajorVersion();
            }
    
            @Override
            public int getMinorVersion()
            {
                return delegateContext.getMinorVersion();
            }
    
            @Override
            public String getMimeType(String s)
            {
                return delegateContext.getMimeType(s);
            }
    
            @Override
            public Set getResourcePaths(String s)
            {
                return delegateContext.getResourcePaths(s);
            }
    
            @Override
            public URL getResource(String s)
                    throws MalformedURLException
            {
                return delegateContext.getResource(s);
            }
    
            @Override
            public InputStream getResourceAsStream(String s)
            {
                return delegateContext.getResourceAsStream(s);
            }
    
            @Override
            public RequestDispatcher getRequestDispatcher(String s)
            {
                return delegateContext.getRequestDispatcher(s);
            }
    
            @Override
            public RequestDispatcher getNamedDispatcher(String s)
            {
                return delegateContext.getNamedDispatcher(s);
            }
    
            @Override
            public Servlet getServlet(String s)
                    throws ServletException
            {
                return delegateContext.getServlet(s);
            }
    
            @Override
            public Enumeration getServlets()
            {
                return delegateContext.getServlets();
            }
    
            @Override
            public Enumeration getServletNames()
            {
                return delegateContext.getServletNames();
            }
    
            @Override
            public void log(String s)
            {
                delegateContext.log(s);
            }
    
            @Override
            public void log(Exception e, String s)
            {
                delegateContext.log(e, s);
            }
    
            @Override
            public void log(String s, Throwable throwable)
            {
                delegateContext.log(s, throwable);
            }
    
            @Override
            public String getRealPath(String s)
            {
                return delegateContext.getRealPath(s);
            }
    
            @Override
            public String getServerInfo()
            {
                return delegateContext.getServerInfo();
            }
        }
    }
    

    Spring MVC中的输入验证 - java

    我知道Commons Validator框架是Struts项目在服务器端和客户端验证输入值的事实上的标准。Spring MVC项目是否也是如此?我得到的印象可能不是,大多数Struts书籍和论坛都谈论Commons Validator框架,但是只有少数Spring书籍和论坛可以。在Spring MVC项目中验证输入的最佳实践是什么?干杯! 参考方案 在引入S…

    Java:“自动装配”继承与依赖注入 - java

    Improve this question 我通常以常见的简单形式使用Spring框架: 控制器服务存储库通常,我会在CommonService类中放一个通用服务,并使所有其他服务扩展到类中。一个开发人员告诉我,最好在每个服务中插入CommonClass而不是使用继承。我的问题是,有一个方法比另一个更好吗? JVM或性能是否会受到另一个影响?更新资料Comm…

    Spring MVC Web应用程序检测暴力攻击的最佳方法? - java

    Spring 3.0 MVC中是否有专门用于帮助检测Web应用程序的身份验证/登录页面上的蛮力攻击的功能? 参考方案 经过长期验证的实践是,如果身份验证失败,则会引入随机但相当大的延迟。这样,合法用户将立即登录,但攻击者每次尝试将花费500ms-1s,这使整个暴力概念不切实际(将永远存在)。合法用户偶尔失败的登录只会使他们稍有延迟,并且不会引起注意。如果需要…

    Spring Data Cassandra的事务管理 - java

    我正在使用Spring和Cassandra作为基础数据库。曾提到过弹簧伞项目“ spring data cassandra”。与休眠不同,在这里无法找到如何管理事务。如果您中的某些人已经合并,请共享要包含的事务管理器的详细信息。 参考方案 Cassandra不支持传统(ACID)的事务。在某些特殊情况下,可以通过一些构造来实现事务原子性,例如原子批处理(请参…

    Spring Boot:java.time.Duration的默认序列化从字符串更改为数字 - java

    我们最近从Spring Boot 2.1.9升级到2.2.1,这导致我们的测试失败。调查导致结果,默认情况下java.time.Duration类型现在序列化为不同的序列。现在,我们将得到"PT15M",而不是在JSON消息中包含字符串"900.0"。 POJO定义如下所示@JsonProperty(required …