如何在同一Tomcat上分端口部署Angular 5与Spring Boot并实现指定请求流程
Hey there, let's walk through how to get your Spring Boot + Angular 5 setup working on the same Tomcat with different ports, and nail that request header → cookie → forward workflow. I’ve built similar setups before, so here’s a step-by-step practical guide:
First, we need to set up Tomcat to listen on two distinct ports (one for your Spring Boot app, one for Angular). Open your Tomcat's conf/server.xml file and add two Connector nodes:
<!-- Spring Boot app will run on port 8080 --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <!-- Angular app will run on port 8081 --> <Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
Next, deploy your apps:
- Package your Spring Boot app as a WAR file (we’ll cover that in the next section) and drop it into Tomcat’s
webappsdirectory (it’ll auto-deploy, usually athttp://localhost:8080/your-spring-boot-app). - Build your Angular 5 app with
ng build --prod, then create a new folder (e.g.,angular-app) inwebappsand copy all the build files into it. This will make your Angular app accessible athttp://localhost:8081/angular-app.
We’ll create a controller to intercept incoming requests, extract the required headers, set them as cookies, then forward the request to your Angular app.
First, adjust your Spring Boot pom.xml to build a WAR (and exclude the embedded Tomcat):
<packaging>war</packaging> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> </dependencies>
Then create a forwarding controller:
import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/") public class RequestForwardController { @GetMapping("**") // Matches all GET requests; adjust for POST/PUT if needed public String forwardToAngular(HttpServletRequest request, HttpServletResponse response) { // Replace these with your actual header names String customHeader1 = request.getHeader("X-External-Header-1"); String customHeader2 = request.getHeader("X-External-Header-2"); // Set cookies that Angular can access if (customHeader1 != null) { Cookie headerCookie1 = new Cookie("external-header-1", customHeader1); headerCookie1.setPath("/"); // Ensures cookie is accessible across the domain headerCookie1.setHttpOnly(false); // Critical: allows Angular's JS to read it headerCookie1.setSecure(false); // Set to true if using HTTPS response.addCookie(headerCookie1); } if (customHeader2 != null) { Cookie headerCookie2 = new Cookie("external-header-2", customHeader2); headerCookie2.setPath("/"); headerCookie2.setHttpOnly(false); headerCookie2.setSecure(false); response.addCookie(headerCookie2); } // Forward to your Angular app's URL return "forward:http://localhost:8081/angular-app"; } }
Key Notes:
- Adjust the request mapping (
@GetMapping("**")) to match only the paths you need to forward (avoid forwarding API endpoints if your Spring Boot app has its own). - If you run into CORS issues (since we’re forwarding to a different port), add a CORS configuration in Spring Boot to allow requests from
http://localhost:8081.
Angular 5 can read cookies using native JavaScript, or you can use a lightweight library (but native works fine for simple cases). Let’s create a cookie service to handle this:
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class CustomCookieService { getCookie(cookieName: string): string | null { const cookieString = "; " + document.cookie; const cookieSegments = cookieString.split("; " + cookieName + "="); if (cookieSegments.length === 2) { return cookieSegments.pop()?.split(";").shift() || null; } return null; } }
Then, use this service in your API service to attach the headers when calling the external app:
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { CustomCookieService } from './custom-cookie.service'; @Injectable({ providedIn: 'root' }) export class ExternalApiService { constructor(private http: HttpClient, private cookieService: CustomCookieService) { } callExternalService() { // Retrieve cookies set by Spring Boot const header1 = this.cookieService.getCookie("external-header-1"); const header2 = this.cookieService.getCookie("external-header-2"); // Build request headers let requestHeaders = new HttpHeaders(); if (header1) { requestHeaders = requestHeaders.set("X-External-Header-1", header1); } if (header2) { requestHeaders = requestHeaders.set("X-External-Header-2", header2); } // Call your external app's endpoint return this.http.get("https://your-external-app-url/api/resource", { headers: requestHeaders }); } }
Key Notes:
- Make sure your external app allows CORS requests from your Angular app’s port (
8081). - If your Angular app is deployed under a context path (like
/angular-app), ensure the cookie’spathis set to/so it’s accessible across the entire domain.
- Send a request from your external service to
http://localhost:8080/your-spring-boot-appwith the required headers (e.g.,X-External-Header-1: value1). - Spring Boot will capture the headers, set them as cookies, then forward the request to your Angular app at
http://localhost:8081/angular-app. - When Angular loads, it reads the cookies and uses them to build headers for requests to the external app.
内容的提问来源于stack exchange,提问作者juniorDeveloper

