【问题标题】:How do I retrieve the URL before @Controller @RequestMapping goes into action?如何在 @Controller @RequestMapping 生效之前检索 URL?
【发布时间】:2019-07-06 16:13:48
【问题描述】:

我继承了一个 JAVA Spring MVC Web 应用程序。我对 Spring MVC 完全陌生,并且在 JAVA 方面非常新手。但我的第一个任务是将应用程序的 URL 添加到已经通过代码生成的电子邮件中。

它基本上是用户单击链接并直接转到特定页面的一种方式。但是,当我尝试在这里看到的所有涉及HttpServletRequest 和更重要的是getRequestURL() 的各种事情时。

Controller 接管后才能获取 URL。我需要的是我将称为引用 URL 的内容——我在浏览器中看到的应用程序 URL。

控制器是一个 REST 服务并返回 localhost:8181/etc/etc,它甚至不包括站点的域。我已经尝试过各种方法,如getHeader("Referer") 等。同样,它们只是返回后控制器 URL。我尝试添加代码以获取正确的 URL 预控制器,然后将其传递给控制器​​方法。仍然给我后控制器 URL。

【问题讨论】:

  • 为了在控制器开始处理之前获取请求,使用HttpFilter。要获取域,请尝试阅读请求的 Host 标头 (request.getHeader("Host"))
  • @ValentinCarnu HttpFilter 是一个低级概念。让它留在纯 Servlets 应用程序上。使用 Spring,我们可以使用更抽象的方法。
  • @LppEdd 过滤器在处理请求时提供了更多选项,在Spring HandlerInterceptor vs Servlet Filters 线程上有一些关于差异的详细信息。 Spring 框架还利用了过滤器和拦截器

标签: java spring-mvc


【解决方案1】:

你需要某种HandlerInterceptorAdapter / HandlerInterceptor
preHandle 方法中,您可以获取HttpServletRequest 对象。

@Override
public boolean preHandle(
        final HttpServletRequest request,
        final HttpServletResponse response,
        final Object handler
) throws Exception {
   // Obtain only the hostname, with the associated port
   final String hostOnly = request.getHeader("Host");

   // Obtain the request URL, excluding query parameters
   final String completeUrl = request.getRequestURL().toString();

   // ... Continue towards the method handler
}

request.getRequestURL() 返回一个 StringBuffer,您可以使用它来操作 URL,然后再从它构建一个 String


如果您需要,可以将相同的 URL 检索概念应用于 @Controller/@RestController 处理程序方法。只需插入一个HttpServletRequest 作为输入参数。

@GetMapping
public ResponseEntity<?> myHandlerMethod(
          final HttpServletRequest request, 
          /* other parameters */) {
   ... 
}

您甚至可以接受WebRequestNativeWebRequest

@GetMapping
public ResponseEntity<?> myHandlerMethod(
          final WebRequest request, 
          /* other parameters */) {
   final String host = request.getHeader("host");
   ...
}

@GetMapping
public ResponseEntity<?> myHandlerMethod(
          final NativeWebRequest request, 
          /* other parameters */) {
   final HttpServletRequest nativeRequest = request.getNativeRequest(HttpServletRequest.class);
   final String host = request.getHeader("host");
   ...
}

根据您的评论进行编辑。

@PostMapping(value = "myurl/{x}/(y)", produces = ...")
public ResponseEntity<String> doSomething(
         final HttpServletRequest request,
         @PathVariable("x") final String x,
         @PathVariable("y") final String y) {
   final String hostOnly = request.getHeader("Host");  // http://yourdomain.com:80

   if (service.sendEmail(x, y, hostOnly)) {
      return new ResponseEntity<>("...");
   } 

   ...

【讨论】:

  • 感谢@LppEdd。但我又回到了原点。 . .错误的网址。 . .本地主机之一。 . .不是来自拦截器的那个。
  • @STP “来自拦截器的那个”是什么意思?准确告诉我您期望的网址
  • 这就是我发布这个问题的原因。在我添加你帮助我的拦截器之前,我从请求后控制器映射中获取“localhost:8181/etc/etc/etc”作为 URL。我需要在控制器接管之前的那个,一旦我设置它,拦截器就会给我。 . .在 preHandle 里面。 . .这就像“myapp.mydomain.com/etc/etc/etc”。我需要从控制器中访问这个 preHandle 变量作为变量传递给我的服务以打印到生成的这封电子邮件。
  • @STP 如果你在“localhost”测试你的应用程序,你会得到“localhost”。您是在本地测试您的应用吗?
  • 不,我不是。我想要作为域 url 的浏览器 url。
【解决方案2】:

UriComponentsBuilder 类型的参数传递给您的控制器方法,它将预先填充用户最初用于发出请求的基本上下文。然后你可以这样做:

String uri = MvcUriComponentsBuilder.relativeTo(uriBuilder)
        .withMethodName(MyController.class, "someMethod", parameterValue)
        .toUriString();

【讨论】:

  • 谢谢,但它给了我 post-Controller@RequestMapping URL,就像所有其他尝试一样。 :-(
  • @STP 然后,您需要添加更多详细信息。也许您的服务位于未正确转发 ForwardedX-Forwarded-For 标头的代理后面。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-21
  • 2016-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多