在前後端分離架構下,瀏覽器同源策略常導致跨域問題。一種經典解法是編寫一個 Servlet 代理,將前端請求轉發至目標伺服器,再將響應原路返回。本文提供一個簡潔可用的 ProxyServlet 實現。
REDIRECT_BASE(目標基礎 URL)。GET 請求,保留原查詢字串。import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ProxyServlet extends HttpServlet {
private static final String COPYRIGHT = com.ibm.dogear.Copyright.SHORT;
public static final String REDIRECT_BASE = "com.ibm.bl.servlet.RedirectServlet.redirect_base";
private String redirectBase;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
redirectBase = getRequiredParam(REDIRECT_BASE);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String queryString = req.getQueryString();
URL url = new URL(redirectBase + (queryString != null ? "?" + queryString : ""));
copyInputStreamToOutputStream(url.openStream(), resp.getOutputStream());
}
private void copyInputStreamToOutputStream(InputStream in, ServletOutputStream out) throws IOException {
try {
try {
byte[] buffer = new byte[1024];
int n;
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
protected String getRequiredParam(String param) throws ServletException {
String result = getServletConfig().getInitParameter(param);
if (result == null) {
throw new ServletException(getClass() + " requires " + param + " param");
}
return result;
}
}
在 web.xml 中註冊 Servlet 並指定初始化參數:
<servlet>
<servlet-name>ProxyServlet</servlet-name>
<servlet-class>com.example.ProxyServlet</servlet-class>
<init-param>
<param-name>com.ibm.bl.servlet.RedirectServlet.redirect_base</param-name>
<param-value>https://target-server.com/api</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ProxyServlet</servlet-name>
<url-pattern>/proxy/*</url-pattern>
</servlet-mapping>
GET,生產環境需補全 POST、Header 轉發、HTTPS 憑證處理。