java怎么重定向POST,DELETE和PUT

我现在在为一个api服务实现一个前后处理的程序,其中只需要对少数几个请求做额外处理,其他请求都可以直接重定向到这个api服务即可。目前我使用了一个拦截器去重定向这些请求:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    boolean redirect = false;
    String uri = request.getRequestURI();
   if (shouldRedirect(uri)){
        response.setStatus(Httpservlet response.SC_TEMPORARY_REDIRECT);
        response.sendRedirect("http://localhost:8080"+uri);
        redirect = true;
    }
    return redirect;
}

但是这个程序只能重定向get请求,我要怎么样才能重定向post,delete和put请求呢?

参考GPT和自己的思路:在 Java 中,使用 HttpURLConnection 类可以重定向 POST、DELETE 和 PUT 请求。以下是一个示例代码,可以在拦截器中使用:

import java.net.HttpURLConnection;
import java.net.URL;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class RedirectInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        if (shouldRedirect(uri)) {
            URL url = new URL("http://localhost:8080" + uri);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setInstanceFollowRedirects(false);
            connection.setRequestMethod(request.getMethod());
            connection.setRequestProperty("Content-Type", request.getContentType());
            connection.setRequestProperty("charset", "utf-8");
            connection.setDoOutput(true);
            connection.getOutputStream().write(getRequestBody(request));
            response.setStatus(connection.getResponseCode());
            response.setContentType(connection.getContentType());
            response.setCharacterEncoding("utf-8");
            response.getOutputStream().write(getResponseBody(connection));
            return false;
        }
        return true;
    }

    private boolean shouldRedirect(String uri) {
        // TODO: 判断是否需要重定向
    }

    private byte[] getRequestBody(HttpServletRequest request) throws IOException {
        // TODO: 获取请求体字节数组
    }

    private byte[] getResponseBody(HttpURLConnection connection) throws IOException {
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = connection.getInputStream();
            out = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int length = 0;
            while ((length = in.read(buffer)) != -1) {
                out.write(buffer, 0, length);
            }
            return out.toByteArray();
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

}

需要注意的是,这里使用了 setInstanceFollowRedirects(false) 来禁止自动重定向。同时,为了将请求体转发到重定向后的接口,需要先获取请求体字节数组,然后再写入到输出流中。同样地,需要将重定向后的响应体写入到 HttpServletResponse 的输出流中。

重定向(Redirect)是指在服务器端让浏览器重新请求另一个 URL 的过程。在 Java 中,可以使用 HttpServletResponse 对象的 sendRedirect() 方法实现重定向。但是,由于 HTTP 协议中的 POST、DELETE 和 PUT 请求需要包含请求体,因此不能直接使用 sendRedirect() 方法来重定向这些类型的请求。解决方法如下:

  1. POST 请求重定向

可以在重定向时把数据作为 URL 参数传递给另一个页面。例如:

response.sendRedirect("nextPage.jsp?param1=value1&param2=value2");

在 nextPage.jsp 页面中,可以通过 request.getParameter() 方法获取这些参数值。但是,如果数据量较大,或者数据需要保密,不适合使用这种方式。

另一种方法是把数据保存在 session 中,然后在重定向时把 session ID 作为 URL 参数传递。例如:

HttpSession session = request.getSession();
session.setAttribute("param1", "value1");
session.setAttribute("param2", "value2");

String sessionId = session.getId();
response.sendRedirect("nextPage.jsp;jsessionid=" + sessionId);

此时在 nextPage.jsp 页面中,可以通过 HttpSession 对象的 getAttribute() 方法获取这些参数值。

  1. DELETE 和 PUT 请求重定向

DELETE 和 PUT 请求通常用于删除和更新资源,因此不应该在重定向时使用。如果需要重定向这些请求,可以使用 POST 请求代替,并在 POST 请求体中包含原始的 DELETE 或 PUT 请求信息。这样可以绕过 HTTP 协议的限制,但需要在后端做相应的处理。例如:

String url = "http://example.com/resource";

HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("DELETE");
connection.connect();

int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
    // 处理成功响应
} else {
    // 处理失败响应
}

response.sendRedirect("nextPage.jsp");

在这个例子中,使用 HttpURLConnection 发送 DELETE 请求,如果响应码为 200,表示删除成功,然后再重定向到下一个页面。同样的方法也可以用于 PUT 请求。

参考GPT:
下面是一个使用拦截器实现重定向GET、POST、DELETE和PUT请求的示例代码:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class RedirectInterceptor implements HandlerInterceptor {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    // 获取请求方法
    String method = request.getMethod();
    // 判断请求方法是否为GET、POST、DELETE或PUT
    if ("GET".equals(method) || "POST".equals(method) || "DELETE".equals(method) || "PUT".equals(method)) {
      // 获取请求路径
      String requestUri = request.getRequestURI();
      // 进行重定向
      response.sendRedirect(requestUri + "/redirected");
      return false;
    }
    return true;
  }

  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {
    // Do nothing
  }

  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
      Exception ex) throws Exception {
    // Do nothing
  }

}

这里实现了Spring框架中的HandlerInterceptor接口,并在preHandle方法中对请求进行拦截。首先获取请求方法,然后判断请求方法是否为GET、POST、DELETE或PUT。如果是,就获取请求路径,并进行重定向。

在上面的示例代码中,重定向的目标路径为/redirected,可以根据实际情况进行修改。需要注意的是,在preHandle方法中进行重定向后,需要返回false,以阻止请求继续处理,否则重定向将不起作用。

此外,上述示例代码只是一个简单的演示,实际情况下可能需要根据请求的类型、请求头、请求参数等信息进行更复杂的判断和处理。

该回答引用GPTᴼᴾᴱᴺᴬᴵ
重定向POST,DELETE和PUT请求需要使用HTTP重定向技术,而不是简单的重定向。HTTP重定向是通过服务器向客户端返回一个特殊的HTTP响应代码,以指示客户端应该向另一个URL发送请求。

对于POST请求,需要在响应中设置状态码为307(Temporary Redirect)或308(Permanent Redirect)以及Location头,指向新的URL。例如:

response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
response.setHeader("Location", "http://localhost:8080/new-url");


对于PUT和DELETE请求,需要在响应中设置状态码为303(See Other)以及Location头,指向新的URL。例如:

response.setStatus(HttpServletResponse.SC_SEE_OTHER);
response.setHeader("Location", "http://localhost:8080/new-url");


请注意,重定向PUT和DELETE请求可能会导致不安全的行为,因为这些请求可能具有副作用。如果可能,应该尽量避免这种情况。

@Requestmapping 注解重定向即可。

上面几个回答都是从一个叫做 openai 的网站由chat gpt机器人程序自动生成的,而这些回答创作根本不需要任何成本,因为 chat gpt 是免费的。如果你喜欢这种水的回答,那么你无需悬赏,自己去那个网站问就可以了。

该回答引用ChatGPT

如有疑问,可以回复我!

重定向POST,DELETE和PUT请求需要使用其他方法,因为这些请求通常都需要提交数据(即请求体),而重定向将导致浏览器向新的URL发送一个新的GET请求,因此不适用于这些请求。以下是一些可以用于重定向POST,DELETE和PUT请求的方法:

使用HTTP 307临时重定向:
HTTP 307状态码表示临时重定向。与HTTP 302(临时重定向)不同,HTTP 307不会更改请求方法,因此POST,DELETE和PUT请求将在重定向后继续使用相同的方法和请求体。您可以像这样在Java中使用HTTP 307:

response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
response.setHeader("Location", "http://localhost:8080"+uri);

使用HTTP 303重定向:
HTTP 303状态码表示重定向。与HTTP 302和307不同,HTTP 303要求客户端将新请求发送到重定向位置的GET方法。因此,您需要在重定向之前将POST,DELETE和PUT请求转换为GET请求,以便在重定向后正确执行。您可以像这样在Java中使用HTTP 303:

response.setStatus(HttpServletResponse.SC_SEE_OTHER);
response.setHeader("Location", "http://localhost:8080"+uri);

使用HTTP 301或302重定向:
虽然不推荐,但您也可以使用HTTP 301或302状态码进行重定向。这将强制客户端将新请求发送到重定向位置的GET方法,但这样可能会导致某些客户端或代理缓存请求体或方法,并且重定向后可能会出现不一致的行为。在Java中,您可以像这样使用HTTP 301或302:

response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 或者SC_MOVED_TEMPORARILY
response.setHeader("Location", "http://localhost:8080"+uri);

请注意,您需要将适当的状态码用于每个方法,例如对于POST请求,应使用HTTP 307或303状态码。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在 HTTP 中,只有 GET 和 HEAD 请求可以被浏览器缓存,其他请求都不能被缓存,包括 POST、PUT 和 DELETE 请求。如果要对这些请求进行重定向,就需要使用 307 Temporary Redirect 状态码,而不是 302 Moved Temporarily 状态码。

在 Java Servlet 中,可以使用 HttpServletResponse 对象的 sendRedirect() 方法来进行重定向。对于 POST、PUT 和 DELETE 请求,需要在重定向之前将请求的参数重新设置到 Location 头中。

下面是一个重定向 PUT 请求的示例代码:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    boolean redirect = false;
    String method = request.getMethod();
    String uri = request.getRequestURI();
    if (shouldRedirect(uri)) {
        String redirectUrl = "http://localhost:8080" + uri;
        if ("POST".equals(method)) {
            redirectUrl = addPostParameters(request, redirectUrl);
        } else if ("PUT".equals(method) || "DELETE".equals(method)) {
            redirectUrl = addBodyParameters(request, redirectUrl);
        }
        response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
        response.setHeader("Location", redirectUrl);
        redirect = true;
    }
    return redirect;
}

private String addPostParameters(HttpServletRequest request, String redirectUrl) throws UnsupportedEncodingException {
    StringBuilder sb = new StringBuilder(redirectUrl);
    Enumeration<String> names = request.getParameterNames();
    if (names.hasMoreElements()) {
        sb.append("?");
    }
    while (names.hasMoreElements()) {
        String name = names.nextElement();
        String value = request.getParameter(name);
        sb.append(URLEncoder.encode(name, "UTF-8")).append("=").append(URLEncoder.encode(value, "UTF-8"));
        if (names.hasMoreElements()) {
            sb.append("&");
        }
    }
    return sb.toString();
}

private String addBodyParameters(HttpServletRequest request, String redirectUrl) throws IOException {
    StringBuilder sb = new StringBuilder();
    BufferedReader reader = request.getReader();
    char[] buffer = new char[1024];
    int read;
    while ((read = reader.read(buffer)) != -1) {
        sb.append(buffer, 0, read);
    }
    return redirectUrl + "#" + URLEncoder.encode(sb.toString(), "UTF-8");
}

这个示例代码首先判断请求的方法是否为 POST、PUT 或 DELETE,如果是则调用对应的方法将请求参数添加到 URL 中。对于 POST 请求,可以直接通过 request.getParameter() 方法获取参数,对于 PUT 和 DELETE 请求,则需要从请求体中读取参数。最后,将重定向 URL 设置到 Location 头中即可。注意,对于 PUT 和 DELETE 请求,需要使用 # 符号将请求体的参数添加到 URL 中。

这个示例代码只重定向了 POST、PUT 和 DELETE 请求,如果需要重定向其他请求,可以在 shouldRedirect() 方法中添加判断条件即可。
如果我的回答解决了您的问题,请采纳!

参考GPT和自己的思路,您可以使用HttpServletResponse对象的sendRedirect()方法来重定向HTTP请求,但这个方法只能用于GET请求,因为它会发送一个HTTP 302重定向响应,该响应会告诉客户端(浏览器),请求的资源已经被暂时移动到一个新的URL地址。而对于POST、PUT、DELETE等请求,由于它们有请求正文(request body)部分,重定向时需要保留请求正文的内容,而HTTP协议没有提供一种简单的机制来处理这种情况。

有一种解决方案是使用代理服务器来转发这些请求。您可以在代理服务器上配置一个重定向规则,将匹配到的请求重定向到另一个地址。代理服务器可以在转发请求时修改请求头和请求正文,以便正确地传递请求信息。

另外,您也可以考虑使用其他的方案来实现您的需求,比如使用Servlet过滤器或Spring拦截器等技术。这些技术可以在请求到达处理器之前或之后对请求进行一些处理。例如,您可以在过滤器或拦截器中读取请求正文,根据需要对请求进行转发或重定向。

以下是一个使用过滤器实现重定向POST请求的示例代码:

public class RedirectFilter implements Filter {
    
    private String redirectUrl;
    private List<String> redirectPaths;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        redirectUrl = filterConfig.getInitParameter("redirectUrl");
        String redirectPathsParam = filterConfig.getInitParameter("redirectPaths");
        redirectPaths = Arrays.asList(redirectPathsParam.split(","));
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        if (redirectPaths.contains(httpRequest.getRequestURI())) {
            // Redirect POST requests
            if (httpRequest.getMethod().equals("POST")) {
                String requestBody = IOUtils.toString(httpRequest.getReader());
                // Perform any necessary modifications to the request body here
                httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
                httpResponse.setHeader("Location", redirectUrl);
                return;
            }
        }

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // Clean up any resources used by the filter
    }
}

这个过滤器会检查请求的URI是否在需要重定向的路径列表中,如果是POST请求,它会读取请求正文并进行必要的修改,然后将请求重定向到指定的URL。其他请求会被传递给下一个过滤器或处理器。

您需要在web.xml文件中配置这个过滤器,例如:

<filter>
    <filter-name>RedirectFilter</filter-name>
    <filter-class>com.example.RedirectFilter</filter-class>
    <init-param>
        <param-name>redirectUrl</param-name>
        <param-value>http://localhost:8080/api</param-value>
    </init-param>
    <init-param>
        <param-name>redirectPaths</param-name>
        <param-value>/path1,/path2</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>RedirectFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

在这个示例中,过滤器将会拦截所有的请求(/*),并将包含在/path1和/path2路径下的POST请求重定向到http://localhost:8080/api%E3%80%82

走网关会更安全一些,不管是从部署还是API自身安全来说

要重定向POST、DELETE和PUT请求,您需要使用一个叫做HTTP方法重写的技术。HTTP方法重写是一种技术,它允许您在重定向期间更改请求的HTTP方法。

为此,您可以将HTTP方法信息存储在请求的头部中,并将请求方法设置为POST,然后将其重定向。这样,在接收到重定向请求时,您可以读取头部信息并使用该信息将请求方法更改为原始请求的方法。

以下是一个示例代码片段,演示如何在拦截器中实现HTTP方法重写:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
boolean redirect = false;
String uri = request.getRequestURI();
if (shouldRedirect(uri)){
response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
response.setHeader("X-Forwarded-Method", request.getMethod());
response.sendRedirect("http://localhost:8080" + uri);
redirect = true;
}
return redirect;
}

在此示例中,我们在重定向响应头中添加了一个名为"X-Forwarded-Method"的自定义头部,其中存储了原始请求的方法。在重定向后,您可以从请求头中读取此信息,并使用它来更改请求方法。

请注意,该方法可能不适用于所有情况,具体取决于您的应用程序需求和重定向目标的限制。在某些情况下,您可能需要考虑其他方案,如代理服务器等。