【问题标题】:Modify HttpServletRequest before any HandlerMapping?在任何 HandlerMapping 之前修改 HttpServletRequest?
【发布时间】:2009-12-28 12:14:31
【问题描述】:

我要解决的问题是我想根据数据库检查所有传入的 GET url。如果 url 存在于数据库中,则应将其传递给某些控制器。我正在使用 Spring 3.0。

首先我尝试创建一个interceptor 并将其添加到 DefaultAnnotationsHandlerMapping。原来我无法修改 preHandle() 中的 url。计划是修改请求中的 url,然后让带注释的控制器处理其余部分。

接下来我尝试制作自定义 HandleMapping。我扩展了AbstractUrlHandlerMapping 并制作了我自己的getHandlerInternal(),它返回一个带有控制器名称的字符串,这正在工作。但我更喜欢一个解决方案,我可以修改请求中的 url 并让带注释的控制器处理它。

在写这篇文章时,我想到也许 servlet 过滤器是最合适的解决方案。如果是这种情况,我可以让 Spring 将 EntityManager 注入过滤器吗?任何我可以扩展的 Spring 类使这更容易?

解决第一段中问题的最正确方法是什么?如果是 servlet 过滤器,请给我一些关于如何编写它的指示。

【问题讨论】:

    标签: java spring spring-mvc


    【解决方案1】:

    我意识到这是一个旧线程,但我建议您扩展 org.springframework.web.servlet.DispatcherServlet 像这样:

    @Override
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            RequestImpl req = RequestImpl.wrapRequest(request, response);
            request = req;
            response = req.getResponse();
        } catch (Throwable t) {
            //swallow       }
        super.doDispatch(request, response);
    }   
    

    然后在您的 web.xml 中将此调度程序称为:

    <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>blah.com.MyDispatcher</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
    

    等等。扩展 Spring MVC 的绝对核心类似乎很可怕,但如果你足够大,可以记住,在注释的黑暗日子之前,当真正的成年人还在致力于我们都喜欢的美丽 POJO 框架时,这就是你的方式重新打算使用 Spring。

    【讨论】:

      【解决方案2】:

      正如其他人所指出的,标准的 servlet 过滤器可以完成这项工作,但它不是一个非常适合 spring 的解决方案 - 过滤器不是由 Spring 管理的,因此不能与 Spring bean 连接。过滤器需要以编程方式获取 spring bean,这不太好。

      修改现有请求的 URL 的问题在于它破坏了 servlet API 模型。 HttpServletRequest 有多种路径和 URL 相关的方法可以提取原始 URL 的不同部分,您必须确保以某种方式修改了所有这些值。无论您使用过滤器还是拦截器,API 都不是为此而设计的。

      因此,与其尝试颠覆 API,我的建议是您编写一个 Spring 控制器,该控制器接受“旧”路径,并根据注入的 EntityManager 将请求转发到“新”路径。可以通过让控制器处理程序方法返回带有“新”路径的InternalResourceView 来进行转发。严格来说,这不是您要转发的视图,但 Spring 不会知道其中的区别。或者,您可以直接使用request.getRequestDispatcher(newPath).forward(request, response) 转发。

      【讨论】:

      • 感谢您的回答,这让我意识到我过度设计了我的解决方案。一个简单的 `RequestMapping(value="/*") 似乎就是我所需要的。
      【解决方案3】:

      也许包装 servlet 请求并将其传递给过滤器链。

      ...
      MyHttpServletRequestWrapper wreq = new MyHttpServletRequestWrapper(request);
      doFilter(wreq, response, chain);
      ...
      

      包装器在询问时返回修改后的 URL。

      【讨论】:

        【解决方案4】:

        您可以使用普通的 javax.servlet.Filter 并创建一个 HttpServletRequest-Wrapper 来为您处理 URL。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-19
          • 1970-01-01
          • 1970-01-01
          • 2011-05-11
          • 1970-01-01
          • 2018-06-05
          • 1970-01-01
          • 2016-09-14
          相关资源
          最近更新 更多