使用 Servlet 别名的传统 Servlet 链接

发布于 2024-12-28 14:56:32 字数 3901 浏览 1 评论 0原文

我正在尝试将现有应用程序从带有 ServletExec 的 IIS 迁移到 tomcat。除了有一个带有两个 servlet 的 servlet 链的情况外,我一切正常。

第一个 servlet 执行一些处理,第二个 servlet 执行一些翻译。

request-->ProcessServlet--> (untranslated html) -->TranslateServlet --> response

就我而言,我可以调用 ProcessServlet,它会生成带有未翻译标签的 html。第二个 servlet 看起来像是采用 html、找到众所周知的翻译标签并翻译它们并向浏览器生成可读的输出。

从谷歌搜索来看,看起来不再支持/推荐使用 servlet 别名的 servlet 链接( 来自此页面)并且可以使用过滤器实现相同的功能,但类必须实现接口,但不幸的是,在我的情况下,我必须使用现有的类文件。

此页面指定了概念,但没有示例。

同样来自此页面

如何使用 Servlet 别名配置 Servlet 链

使用设置部分的 Servlet Aliasing 小节 管理工具,可以为特定的 Servlet 列表命名 网址请求。在 servlets 表中,添加新映射时,您可以 允许按以下顺序输入以逗号分隔的 servlet 列表 当请求到达时应该调用它们 特定的网址。这将配置一个 servlet 链,以便每隔 与 URL 匹配的请求到达的时间。

任何人都可以指定一个示例或为我指明如何从 web.xml 使该链工作的正确方向吗?

更新:

根据 kschneid 在他的回答中的概述,这是对我有用的完整实现

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class TranslateFilter implements Filter {

  private FilterConfig config = null;

  public void init(FilterConfig config) throws ServletException {
    this.config = config;
  }

  public void destroy() {
    config = null;
  }

  public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {

        HttpServletResponse httpResponse = (HttpServletResponse) response;
        MyHttpServletResponseWrapper processResponse  =   new MyHttpServletResponseWrapper(httpResponse);
        chain.doFilter(request, processResponse );
        String content = processResponse.toString();
        config.getServletContext().log("CONTENT: " + content);
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        MyHttpServletRequestWrapper processResponseAsRequest = new MyHttpServletRequestWrapper(httpRequest, content);

        RequestDispatcher dispatch = request.getRequestDispatcher("/Translate");
        response.setContentType("text/html");
        dispatch.forward(processResponseAsRequest, response); // forward to translate servlet with response from process servlet as the request and the original response
  }

}

class MyHttpServletResponseWrapper 
  extends HttpServletResponseWrapper {

  private StringWriter sw = new StringWriter();

  public MyHttpServletResponseWrapper(HttpServletResponse response) {
    super(response);
  }

  public PrintWriter getWriter() throws IOException {
    return new PrintWriter(sw);
  }

  public ServletOutputStream getOutputStream() throws IOException {
    throw new UnsupportedOperationException();
  }

  public String toString() {
    return sw.toString();
  }
}

class MyHttpServletRequestWrapper 
  extends HttpServletRequestWrapper {
    private String content;
    public MyHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    public MyHttpServletRequestWrapper(HttpServletRequest request, String content) {
        super(request);
        this.content = content;
    }

    public ServletInputStream getInputStream()
    {
        return new MyServletInputStream(content);
    }

    public BufferedReader getReader()
    {
        InputStreamReader in= new InputStreamReader(getInputStream());
        return new BufferedReader(in);
    }
  }

class MyServletInputStream extends ServletInputStream
{
    private InputStream is;

    public MyServletInputStream(String content)
    {
        is = new ByteArrayInputStream(content.getBytes());
    }

    public int read() throws IOException
    {
        return is.read();
    }
}

I'm trying to migrate an existing application from IIS with ServletExec to tomcat. I got everything working except for the case where there is a servlet chain with two servlets.

The first servlet does some processing and the second servlet does some translation.

request-->ProcessServlet--> (untranslated html) -->TranslateServlet --> response

In my case, I can call the ProcessServlet and it produces html with untranslated tags. The second servlet looks like it takes the html, locates well known translation tags and translates them and produces readable outupt to the browser.

From googling, looks like servlet chaining using servlet aliasing is no longer supported/recommended( from this page) and the same functionality can be achieved with filters but the classes have to implement an interface but unfortunately in my case I have to work with the existing class files.

This page specifies the concept but has no examples.

Also from this page

How to Configure a Servlet Chain Using Servlet Aliasing

Using the Servlet Aliasing subsection of the setup section in the
Administration Tool, a list of servlets can be named for a particular
URL request. In the servlets table, when adding a new mapping, you are
allowed to enter a comma-separated list of servlets in the order in
which they should be invoked when a request arrives for that
particular URL. This configures a servlet chain to be invoked every
time a request that matches the URL arrives.

Can anyone specify an example or point me in the right direction as to how to get this chain to work from web.xml?

UPDATE:

Per kschneid's outline in his answer, here's the full implementation that worked for me

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class TranslateFilter implements Filter {

  private FilterConfig config = null;

  public void init(FilterConfig config) throws ServletException {
    this.config = config;
  }

  public void destroy() {
    config = null;
  }

  public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {

        HttpServletResponse httpResponse = (HttpServletResponse) response;
        MyHttpServletResponseWrapper processResponse  =   new MyHttpServletResponseWrapper(httpResponse);
        chain.doFilter(request, processResponse );
        String content = processResponse.toString();
        config.getServletContext().log("CONTENT: " + content);
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        MyHttpServletRequestWrapper processResponseAsRequest = new MyHttpServletRequestWrapper(httpRequest, content);

        RequestDispatcher dispatch = request.getRequestDispatcher("/Translate");
        response.setContentType("text/html");
        dispatch.forward(processResponseAsRequest, response); // forward to translate servlet with response from process servlet as the request and the original response
  }

}

class MyHttpServletResponseWrapper 
  extends HttpServletResponseWrapper {

  private StringWriter sw = new StringWriter();

  public MyHttpServletResponseWrapper(HttpServletResponse response) {
    super(response);
  }

  public PrintWriter getWriter() throws IOException {
    return new PrintWriter(sw);
  }

  public ServletOutputStream getOutputStream() throws IOException {
    throw new UnsupportedOperationException();
  }

  public String toString() {
    return sw.toString();
  }
}

class MyHttpServletRequestWrapper 
  extends HttpServletRequestWrapper {
    private String content;
    public MyHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    public MyHttpServletRequestWrapper(HttpServletRequest request, String content) {
        super(request);
        this.content = content;
    }

    public ServletInputStream getInputStream()
    {
        return new MyServletInputStream(content);
    }

    public BufferedReader getReader()
    {
        InputStreamReader in= new InputStreamReader(getInputStream());
        return new BufferedReader(in);
    }
  }

class MyServletInputStream extends ServletInputStream
{
    private InputStream is;

    public MyServletInputStream(String content)
    {
        is = new ByteArrayInputStream(content.getBytes());
    }

    public int read() throws IOException
    {
        return is.read();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

2025-01-04 14:56:32

我不太熟悉 servlet 链接的实现细节,但这里有一个可能有效的通用方法。将两个 servlet 映射到不同的 URL:

<servlet-mapping>
    <servlet-name>process</servlet-name>
    <url-pattern>/process</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>translate</servlet-name>
    <url-pattern>/translate</url-pattern>
</servlet-mapping>

然后将过滤器映射到 process servlet:

<filter-mapping>
    <filter-name>processChain</filter-name>
    <servlet-name>process</servlet-name>
</filter-mapping>

processChain 过滤器会执行以下操作:

public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {
    ServletResponseWrapper processResponse = ...; // response buffer
    chain.doFilter(request, processResponse); // let process servlet populate response buffer
    ServletRequestWrapper processResponseAsRequest = ...; // use processResponse to create request for translate servlet
    RequestDispatcher dispatch = request.getRequestDispatcher("/translate");
    dispatch.forward(processResponseAsRequest, response); // forward to translate servlet with response from process servlet as the request and the original response
}

...或类似的操作;)

I'm not really familiar with the implementation details of servlet chaining, but here's a general approach that might work. Map the two servlets to different URLs:

<servlet-mapping>
    <servlet-name>process</servlet-name>
    <url-pattern>/process</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>translate</servlet-name>
    <url-pattern>/translate</url-pattern>
</servlet-mapping>

Then map a filter to the process servlet:

<filter-mapping>
    <filter-name>processChain</filter-name>
    <servlet-name>process</servlet-name>
</filter-mapping>

The processChain filter would do something like:

public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {
    ServletResponseWrapper processResponse = ...; // response buffer
    chain.doFilter(request, processResponse); // let process servlet populate response buffer
    ServletRequestWrapper processResponseAsRequest = ...; // use processResponse to create request for translate servlet
    RequestDispatcher dispatch = request.getRequestDispatcher("/translate");
    dispatch.forward(processResponseAsRequest, response); // forward to translate servlet with response from process servlet as the request and the original response
}

...or something like that ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文