如何让Java/Spring/Tomcat环境下的webapp1.war嵌入webapp2.war内容?
解决方案:在webapp1中访问webapp2的内容
这是个很实际的场景,我来给你拆解下可行的方案和需要注意的坑:
先讲为啥直接用JSP include不行
咱们平时用的<jsp:include>或者<%@ include %>都是针对同一个Web应用内部的资源加载,Tomcat默认会隔离不同Web应用的类加载器和上下文,跨应用直接用include标签会直接报错,因为根本找不到webapp2的资源路径。
可行的三种方案
1. 写一个内部代理组件(无需修改Tomcat配置)
在webapp1里新增一个Servlet或者Spring Controller,作为“中间层”,帮用户转发请求到webapp2,再把响应返回给用户。具体步骤:
- 因为两个应用在同一台服务器上,你可以用本地地址调用webapp2,比如
http://localhost:8080/webapp2/xxx(安全团队禁止的是外部访问,内部本地请求通常是允许的,先确认这点) - 代码示例(用Spring Controller举例):
@GetMapping("/webapp2-proxy/**") public ResponseEntity<Object> proxyToWebapp2(HttpServletRequest request, HttpServletResponse response) throws IOException { // 获取用户请求的webapp2路径(去掉前缀/webapp2-proxy) String path = request.getRequestURI().replace("/webapp2-proxy", ""); String webapp2Url = "http://localhost:8080/webapp2" + path; // 复制用户的请求头(尤其是SSO相关的Cookie,确保webapp2能识别用户身份) HttpHeaders headers = new HttpHeaders(); Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); headers.add(headerName, request.getHeader(headerName)); } // 发送请求到webapp2 HttpEntity<String> entity = new HttpEntity<>(headers); ResponseEntity<String> webapp2Response = restTemplate.exchange(webapp2Url, HttpMethod.valueOf(request.getMethod()), entity, String.class); // 把webapp2的响应返回给用户 return ResponseEntity.status(webapp2Response.getStatusCode()) .headers(webapp2Response.getHeaders()) .body(webapp2Response.getBody()); } - 注意点:要处理Cookie、请求方法(GET/POST)、文件上传这些特殊场景,还要防范SSRF风险——必须严格限制请求只能指向本地的webapp2,不能让用户篡改目标URL。
2. 配置Tomcat跨上下文访问(需要服务器权限)
Tomcat支持开启跨上下文访问,让webapp1直接获取webapp2的上下文,从而转发请求:
- 修改Tomcat的
conf/server.xml,给两个应用的<Context>节点加上crossContext="true":<Context path="/webapp1" docBase="webapp1.war" crossContext="true"/> <Context path="/webapp2" docBase="webapp2.war" crossContext="true"/> - 然后在webapp1的JSP或Servlet里,就可以直接转发请求到webapp2:
// 在Servlet里的写法 ServletContext webapp2Context = getServletContext().getContext("/webapp2"); RequestDispatcher dispatcher = webapp2Context.getRequestDispatcher("/index.jsp"); // 转发请求,用户看不到webapp2的地址 dispatcher.forward(request, response); - 注意点:这个方案需要修改Tomcat全局配置,得和运维/服务器管理员沟通;另外安全团队可能会顾虑跨上下文打破了应用隔离,要提前确认安全性。
3. 合并两个应用(最简单但耦合性高)
如果webapp2的功能不复杂,直接把webapp2的代码、JSP、静态资源全部复制到webapp1里,重新打包成一个war包。这样就不存在跨应用访问的问题了,但缺点是两个应用会耦合在一起,后续单独维护会很麻烦,适合小体量的应用。
安全必注意的点
- 不管用哪种方案,都要确保webapp2的内容只能被已通过SSO认证的用户访问——代理/转发的请求必须带上用户的SSO凭证(比如Cookie),不能让匿名用户通过webapp1访问webapp2。
- 如果用代理方案,一定要严格校验目标URL,防止被用来发起恶意内部请求(SSRF攻击)。
内容的提问来源于stack exchange,提问作者user550738
相关产品推荐
相关产品推荐

