java 如何外部化 web.xml servlet init-param?Spring DelegatingFilterProxy for Servlets?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2845649/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:07:01  来源:igfitidea点击:

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

javaspringservlets

提问by jnorris

I have a 3rd-party servlet that I cannot modify. It accepts an init-paramthat I would like to externalize (from web.xml).

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

I can externalize a servlet filter init-paramusing DelegatingFilterProxy. This effectively moves the servlet filter definition into Spring where there are much more powerful externalization tools (eg: PropertyPlaceholderConfigurer, environment variables, etc.)

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

How can I do this for a servlet?

如何为 servlet 执行此操作?

回答by mdma

Looks like you need a DelegatingServletProxyclass, 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.
  2. Add a servlet to your web.xml whose implementing class is this DelegatingServletProxy. This replaces your existing serlvet that you want to change the init-params for. You set the init params for this new servlet: proxyServletClass is the name of the class of your servlet. proxyServletParams is the name of a Properties bean in your spring config. This properties bean is used to set the init params for the proxied servlet.
  3. In your spring config, add a new Properites bean that defines the init-params
  1. 在 web.xml 中设置常用的 spring 上下文配置/ContextListener 为您的 web 应用程序设置应用程序范围的 spring 上下文。
  2. 将 servlet 添加到您的 web.xml,其实现类是此 DelegatingServletProxy。这将替换您要为其更改 init-params 的现有 serlvet。您为这个新的 servlet 设置 init 参数:proxyServletClass 是您的 servlet 类的名称。proxyServletParams 是 spring 配置中的 Properties bean 的名称。此属性 bean 用于设置代理 servlet 的 init 参数。
  3. 在您的 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.xmlsnippet

示例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. It's untested - should be considered a starting point.

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

回答by skaffman

Sounds like ServletWrapperControlleris what you need.

听起来ServletWrapperController就是你所需要的。

Spring Controller implementation that wraps a servlet instance which it manages internally. Such a wrapped servlet is not known outside of this controller; its entire lifecycle is covered here

Spring Controller 实现,它包装了它在内部管理的 servlet 实例。这种封装的 servlet 在这个控制器之外是未知的;这里涵盖了它的整个生命周期

 <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 处理程序映射来路由到它。