简体   繁体   English

如何外化web.xml servlet init-param? Servlets的Spring DelegatingFilterProxy?

[英]How to externalize web.xml servlet init-param? Spring DelegatingFilterProxy for Servlets?

I have a 3rd-party servlet that I cannot modify. 我有一个我无法修改的第三方servlet。 It accepts an init-param that I would like to externalize (from web.xml). 它接受我想要外化的init-param (来自web.xml)。

I can externalize a servlet filter init-param using DelegatingFilterProxy . 我可以使用DelegatingFilterProxy外化servlet过滤器init-param This effectively moves the servlet filter definition into Spring where there are much more powerful externalization tools (eg: PropertyPlaceholderConfigurer, environment variables, etc.) 这有效地将servlet过滤器定义移动到Spring中,其中有更强大的外化工具(例如:PropertyPlaceholderConfigurer,环境变量等)

How can I do this for a servlet? 我怎样才能为servlet做这个?

Looks like you need a DelegatingServletProxy class, although this doesn't exist in Spring However, I imagine it is pretty straightforward to code, using DelegatingFilterProxy as a starting-point. 看起来你需要一个DelegatingServletProxy类,虽然这在Spring中不存在但是,我认为编码非常简单,使用DelegatingFilterProxy作为起点。

A servlet only implements a handful of concrete methods, so delegating should be straightforward. servlet只实现了一些具体的方法,因此委托应该是直截了当的。

Ok, I put my money where my mouth is! 好吧,我把钱放在嘴边! EDIT: Below a basic implementation of DelegatingServletProxy . 编辑: 下面是DelegatingServletProxy的基本实现

You use it like this: 你这样使用它:

  1. Setup the usual spring context configuration/ContextListener in web.xml to set the application-wide spring context for your webapp. 在web.xml中设置常用的spring上下文配置/ ContextListener,为webapp设置应用程序范围的spring上下文。
  2. Add a servlet to your web.xml whose implementing class is this DelegatingServletProxy. 将servlet添加到web.xml,其实现类为DelegatingServletProxy。 This replaces your existing serlvet that you want to change the init-params for. 这将取代您想要更改init-params的现有serlvet。 You set the init params for this new servlet: proxyServletClass is the name of the class of your servlet. 为这个新的servlet设置init参数:proxyServletClass是servlet类的名称。 proxyServletParams is the name of a Properties bean in your spring config. proxyServletParams是spring配置中的Properties bean的名称。 This properties bean is used to set the init params for the proxied servlet. 此属性bean用于为代理的servlet设置init参数。
  3. In your spring config, add a new Properites bean that defines the init-params 在spring配置中,添加一个定义init-params的新Properites bean

Some examples, in the spring application context 一些示例,在spring应用程序上下文中

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

Example web.xml snippet 示例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>

Here's the servlet code, it's quite long, but most of it is delegating ServletContext - the interesting stuff happens at the top. 这是servlet代码,它很长,但大多数是委托ServletContext - 有趣的东西发生在顶部。 It's untested - should be considered a starting point. 它未经测试 - 应该被视为一个起点。

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();
        }
    }
}

Sounds like ServletWrapperController is what you need. 听起来像ServletWrapperController是你需要的。

Spring Controller implementation that wraps a servlet instance which it manages internally. Spring Controller实现,它包装它在内部管理的servlet实例。 Such a wrapped servlet is not known outside of this controller; 这种包装的servlet在该控制器之外是未知的; its entire lifecycle is covered here 它的整个生命周期都在这里

 <bean id="strutsWrappingController" class="org.springframework.web.servlet.mvc.ServletWrappingController">
   <property name="servletClass" value="org.apache.struts.action.ActionServlet"/>
   <property name="servletName" value="action"/>
   <property name="initParameters">
     <props>
       <prop key="config">/WEB-INF/struts-config.xml</prop>
     </props>
   </property>
 </bean>

This will let you treat the legacy servlet like other Spring controller, so you use normal Spring MVC handler mappings to route to it. 这将让您像其他Spring控制器一样处理遗留servlet,因此您可以使用普通的Spring MVC处理程序映射来路由它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM