在类似 Web 应用程序之间共享 Web 层代码(控制器和 JSP)的最佳实践

Posted

技术标签:

【中文标题】在类似 Web 应用程序之间共享 Web 层代码(控制器和 JSP)的最佳实践【英文标题】:Best practices for sharing web-tier code (Controllers and JSPs) between similar web apps 【发布时间】:2012-03-24 16:54:53 【问题描述】:

我正在重写一些老化的 Web 应用程序。特别是有两个非常非常相似,但今天没有共享代码,我的目标是解决这个问题。

项目正在用 Maven、Spring MVC 和 Sitemesh 重写。

模型层代码很容易使用 JAR 共享。但我不知道有什么好的方法可以在相似的应用程序之间共享通用的网络层代码(JSP 和控制器)。

这里有一些背景。这些应用程序是网上商店。一个是普通商店(想想 amazon.com),用户可以登录、搜索产品、添加到购物车并结账。另一个基本上是一样的,只是它是一个punchout站点。产品浏览和购物车部分是相同的。但是,登录和结帐是完全不同的。

我过于简单化了,但这足以说明问题。产品浏览和购物车部分中有很大一部分网络层代码应该能够在两者之间共享。

我认为不可能简单地将相同的 WAR 文件作为基于环境变量的“模式”或来自不同数据库的设置运行。其中一个区别是完全不同的 Spring Security 配置。最好将其他站点的登录和结帐控制器排除在组件扫描之外,这样没有人可以通过 URL 操作以某种方式越过错误的控制器。

我最初开始使用 Maven 配置文件和过滤来在同一个 WAR 项目中保留两个不同的配置集(web.xml、spring configs 等)。根据选择的 Maven 配置文件,生成的 WAR 使用不同的配置集构建(为了清楚起见,使用不同的名称)。这违反了一个 pom 产生一个工件的 Maven 原则。

有没有更好的方法来做到这一点? Maven WAR Overlays 呢?我看到人们谈论使用覆盖来共享常见资源,如 CSS、JS、图像,甚至一些常见的 JSP。但我没有看到任何人提到以这种方式共享控制器之类的类。

我可以将 Controller 类下放到 JAR 中,但从逻辑上讲,它们似乎应该保留在各自的 JSP 中。而且 JSP 也不能下推到 JAR(对吗?)。

我还考虑过让它成为一个包含多个 WAR 文件的 EAR——一个 WAR 用于常见的购物体验,另一个 WAR 用于适当的登录和结帐。我相信会话可以在同一个 EAR 中的两个 WAR 之间共享,但我不确定它是否与 Spring 的会话范围 bean 配合得很好。我听说它们并没有真正存储在会话中。我还必须弄清楚如何处理用于页眉/页脚的 Sitemesh 装饰器。需要将相同的 Sitemesh 配置及其资源复制到两个 WAR 中,对吗?所以最终,购物 WAR 神器在每种情况下仍然会有所不同。

我必须相信其他人之前已经处理过这个问题。我想错了吗?这类事情有通用的解决方案吗?

【问题讨论】:

【参考方案1】:

在与复制粘贴作斗争方面做得很好。为什么你说很难共享 JSP?您可以使用 maven 依赖插件将它们从共享 jar 中复制出来:

 <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
         <version>2.4</version>
         <executions>
           <execution>
             <id>unpack</id>
             <phase>package</phase>
             <goals>
               <goal>unpack</goal>
             </goals>
             <configuration>
               <artifactItems>
                 <artifactItem>
                   <groupId>com.example</groupId>
                   <artifactId>webapp-common</artifactId>
                   <version>1.0-SNAPSHOT</version>
                   <outputDirectory>[target jsp directory]</outputDirectory>
                   <includes>**/*.jsp</includes>
                 </artifactItem>
               </artifactItems>
             </configuration>
           </execution>
         </executions>
       </plugin>

【讨论】:

这是一个巧妙的技巧,我最终可能会接受它,因为我认为我们从未放弃过 Maven。一个显而易见的缺点是,如果 JSP 是从 JAR 中复制出来的,那么开发人员就不能再即时更新它。需要从 IDE 重新构建和重新部署才能看到简单的编辑。我怀疑对此有什么可以做的,但如果你有想法,我会全力以赴。 嗯......你可能会用符号链接做一些肮脏的事情,这取决于你准备让你的开发环境与最终工件有多大不同。或者,如果您使用的是爆炸式 WAR,则在每次 JSP 更改后,它自己运行单个 maven unpack 目标并不需要很长时间。【参考方案2】:

在这种情况下,我的首选选项是将所有相关文件(控制器、js、图像...)放在一个 jar 中。但是这里的问题是 JSP 文件的使用:如果它们在 jar 中,就没有简单的方法可以使用它们。但是使用 VelocityFreemarker 等其他视图技术,这可以通过简单的方式实现,并具有其他优势。我不知道这是否会导致您工作过多,但对于有这些需求的新项目来说,这是最好的选择。

【讨论】:

有趣...所以您是说我们可以从 /WEB-INF/velocity 或 JAR 中提取 Velocity/Freemarker 模板?这是否需要自定义 ViewResolver 才能使用 Spring MVC 完成?我找到的所有示例都只是参考 /WEB-INF。 这里有一个很好的例子:springbyexample.org/examples/velocity-email-template.html【参考方案3】:

我们在这里使用 Subversion,并使用 svn:externals(有点像符号链接)以便在项目之间共享某些公共代码(主要是 .jsp 文件)。工作得相当好,我们使用的是 OC4J,它实际上有一种在多个项目之间共享 .jsp 的方法,但是由于我们目前正在转向 Tomcat(或其他东西),所以我想提出一种与容器无关的方法来做到这一点。

【讨论】:

【参考方案4】:

Sinuhepop 是对的,但他的答案并不完美。

这是完美的答案。您必须参考以下网址,它可以帮助您。

click here

在url页面中,属性内容框的例子不准确,你跟我来:

如果需要共享文件:

a.jsp  svn://myhome.com/svn/myproject/trunk/a.jsp

如果需要共享文件夹:

xml  svn://myhome.com/svn/myproject/trunk/xml

【讨论】:

以上是关于在类似 Web 应用程序之间共享 Web 层代码(控制器和 JSP)的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

在 Elastic Beanstalk Web 和工作程序层之间共享数据

在控制台和 Web 应用程序之间共享 AppSettings 和 ConnectionStrings

web 应用程序之间如何通信,共享和传输数据

Webpack:Webworker 和 Web 代码之间共享代码的通用块?

ASP.Net 分层应用程序 - 在层之间共享实体数据模型

Android 和 Web App 共享 Kotlin 代码