J2EE开发原则

J2EE,作为开发mission-critical的企业级应用的一整套规范的整合平台,规范多、内容广,从而给开发J2EE应用带来了很多“麻烦”。比如,为实现内容的RDBMS存储,我们可能的方法有JDBC、Entity Beans、JDO、O/R Mapping工具(TopLink、Hibernate)、XML-DBMS、JAXB等方法(其中一些方法不是J2EE规范所包含的)。因此,为实现J2EE各层(至少有表示层、控制层、商业逻辑层等3层)以及层与层之间的耦合,J2EE系统架构师需要考虑的问题会很多。加上,J2EE本身的快速发展,给架构、开发具有工业强度的J2EE应用带来一些难题。
  同时,软件开发技术从来就没有“银弹”,所以J2EE技术也不是万能的。但是,如果我们在结合具体商业需求的基础上,合理的应用好J2EE技术,其结果可想而知。本文试图从本人以往的项目经验入手,来探讨开发J2EE应用时应该遵循的几点准则,希望起到抛砖引玉的作用。本文结合JBoss 3.2.1下的J2EE应用开发为例展开论述。
  1.结合商业需求选择合理的架构
  如果脱离商业需求,而单独的讨论技术本身的优势是不够的。各项技术都有产生的特定背景,其中很多都是来自工业需求而触动的。一般而言,企业信息系统(EIS)都要求自己稳定、安全、可靠、高效、便于维护。同时,各个企业信息系统都有自己独特的要求,可能有些时候需要考虑与原有遗留系统的集成,所以了解各个企业信息系统具体的商业需求对于整个系统的架构显得很关键。
  比如,如果待开发的J2EE应用系统中使用到的数据大部分来自于外在数据源;而这些数据可能是通过JDBC直接从外在数据源导入到待开发的J2EE系统的Database中。对于这种情形,如果在开发过程中,仅仅使用JDBC来操作数据库,对于小强度(并发访问用户少、数据流量少)的情形,显然是比较合适的;但如果,并发访问用户较多、数据流量大,对Database层使用较为频繁的情形,则显得有些力不从心。因此,对于这种需求,我们可以考虑采用Entity Beans with Caches。打个比方,在JBoss 3.2.1中对于Entity Beans的Cache策略有多种,这时可以考虑使用,,即“Standard CMP 2.x EntityBean”,方式并采用“D”类型的commit-option来保证Entity Beans的内容与数据源的同步,并使得系统的性能得到大大改善(同直接使用JDBC相比)。其中,可以将一些Entity Beans设置为read-only,以改善性能。当然,在这里也可以采用其他一些O/R Mapping技术,比如TopLink。
  再比如,考虑这样一种情形:如果待开发的企业信息系统使用到的数据都是由系统本身生成和操作的,则建议采用:CMP Entity Beans技术。Entity Beans给大家的印象很坏,这可能与EJB 1.1给大家留下的坏映象有关吧。但是,EJB 2.0(或者说2.1)得到了很大的改善,Local Interfaces、CMR、Read-Only、Session Fa?ade模式给Entity Beans注入了活力。当然,并发用户多、数据流量很大时才会体现出使用Entity Beans的优势。其中,有一点很关键:要注重Entity Beans技术的性能调优,各个应用服务器都有自己的一套性能调优方案。对于JBoss 3.2.1,配置文件standardjboss.xml提供了Entity Beans技术调优的入口。比如,Bean Lock策略的合理使用对于Entity Beans的调优就显得很重要。这样使得,我们可以更加关注于系统的商业逻辑,而不只是底层的Database(EJB调优处于EJB Container中,因此我们处在J2EE性能的高端,而不是底端,即Database层。同时,Database层的调优使得J2EE系统的数据库移植性大打折扣。)。
  简而言之,要结合各个系统的特定需求和状况给出具体的技术架构方案,而不能孤单的论述技术本身的好坏。
  2.Framework的合理选用
  设计模式在J2EE应用系统中扮演着重要的角色。因此,有一个问题摆在大家面前,是自己来实现具体的设计模式,还是借助于Third-party Framework。如果贵公司不大,或者说公司不想在J2EE基础应用Framework投入很多精力,选用现有的较为成熟的、稳定、与现有J2EE Specification兼容的技术框架会比较明智。
  一般而言,Framework本身,或者说J2EE平台本身都是实现并优化了具体的设计模式、规则,比如业务代理、Service Locator(包括Web Tier和EJB Tier各自的服务定位器,起到统一管理有限资源、Cache相关资源的作用,便于系统移植)、Front Controller、DAO等等。现有的J2EE Framework比较丰富。比如:
  Struts: 对于实现了Model 2类型的Framework,对于现在以及将来(随着JSF规范、技术的成熟),选用她是一种明智之举。目前,Struts已经发展到1.1版本。其内在的MVC主线、对后端数据操作方式没有限定、集合了Apache Jakarta项目组的优秀相关项目的精华,可谓是开发J2EE应用的佳品。同时,对于具有.NET Web Forms功能的下一代J2EE平台技术JSF而言,Struts本身可考虑到与JSF的兼容和集成性。比如,通过JSP呈现表示层、Servlet呈现控制层、EJB呈现数据存储层。各层之间,可以通过值对象、HTTP相关对象来通讯,实现J2EE相关技术的完美应用。
  Log4j: 我想对于习惯采用“System.out.println(“”);”的读者而言,Log4j是大家的福音。尽管Java 2 Standard Edition也具备java.util.logging包来保证日志的输出,但Log4j的简单、高效、灵活已经成了很多项目的选择。日志,在某种程度上可以考验系统的稳定性、正确性,所以采用可配置的Log4j(目前,Log4j已经考虑到了与java.util.logging包的兼容性)是不会错的。比如,JBoss 3.2.1本身就是借助于Log4j来管理日志的。
  realMethods: 可能有些读者还不知道这一款杀手锏。那好,这里就简要作一介绍。realMethods是一开发J2EE应用的Framework,她不同于Struts(主要在于实现Model 2,J2EE应用前端);realMethods对于J2EE应用的各个层面都有详尽、高效的支持。同时,realMethods以前还是商用软件,现在已经成为了Open Source的产品,因此现在可以参看其全部源代码。
  BC4J: Oracle公司推出的用于Java的商业组件。其内容和外在的特点和优势,不言而喻。
  当然,类似的Framework很多很多。作为开发J2EE应用的团队而言,我们需要对各种Framework加以筛选,选择适合项目需求、团队、公司发展方向的框架。
  一般情况下,待开发的目标产品不宜采用过多的Framework。其一,J2EE各个技术发展很快,过多的Framework使得系统的后续升级、维护不利;其二,可以借鉴其中的好的一面,比如研究realMethods实现的相应的设计模式,并改造她以适合我们的项目需求;其三,Framework本身会有变动,如果选用过多,会给开发团队加重负担,从而不利于项目管理。有选择的使用现有的成熟Framework能提升大家的开发效率、开发水平。
  3,开发模式的选择
  开发J2EE应用要求目标开发人员能够掌握其中的各种技术。但是,现实情况不是这样。作为一个团队,每个人都有自己不同的技能优势、兴趣以及悟性。同时,J2EE本身需要体现社会分工。一般情况下,我们的开发团队不会有Specification所要求的各个开发角色。现实往往只有3种(也可能是两种):美工、JSP程序员、EJB程序员。面对这种分工,团队更要注重沟通、交流,注重代码的一致性。
  一般情况下,团队要尽量采用版本控制工具管理代码、尽量做到每天都有一个完整的运行版本。经过一段时间,团队都会适应这种开发模式。其中,版本控制工具一定要使用,便于代码的管理、控制和备份。这其中会牵扯到很多层面。比如,开发工具的选择要考虑到版本控制工具的使用、建模工具的合理使用有助于团队有效的沟通和交流。
  基于现有的开发模式,个人认为这样3套方案不错。第一,采用Together作为建模工具、采用JBuilder作为IDE工具、采用VSS(或者CVS)作为版本控制工具、采用JBoss作为开发J2EE应用开发阶段的服务器。第二,采用WebSphere Studio整套工具。第三,采用Eclipse(或者JCreator)、Ant、XDoclets作为开发工具。
  当然,手工完成J2EE应用的编写、编译、打包、部署、测试更能使开发者理解各个开发阶段的具体细节。但本人认为,只要开发者有这种关注具体细节的态度,选用功能强大的建模、开发工具是明智的。开发工具不能提高开发人员的开发技能,但是她能够引导开发人员正确的开发方向。比如,JBuidler 9 Enterprise提供的EJB精灵具有的“Struts + EJB + Session Fa?ade + Value Object”等功能呈现了业界广泛应用的J2EE构架方式。
  4,注重各个阶段的测试工作
  测试工作往往是很多项目经理忽视,不愿意去花费时间、费用的内容,因为那样会增加项目的成本。但是,他们忽视了,项目的完成质量往往对项目的成本有很大的关系。比如,如果软件质量很差,并没有经历测试阶段,其后期部署、运行所带来的费用会远远超过前期的费用。
  测试是分阶段的。单元测试,比如借助于JUnit,来保证功能正确等内容。集成测试,来保证系统没有内存泄漏等内容。其中,Optimizeite Suite Enterprise对于完成Profiler、Code Coverage、Thread Debugger等内容很有帮助。我记得,我写的一个Swing桌面应用存在内容泄漏,但是想了很多办法都没有解决问题。后来,采用Profiler获得了答案。因此,现在开发应用,我们很多时候都采用Optimizeite Suite Enterprise作为测试工具。尤其是,在做集成测试过程中,检查系统的内存泄漏、性能很有帮助。
  测试是分类型的。压力测试、性能测试。就目前对支持J2EE应用的测试而言,并没有很好的测试工具。但是,一般情况下,借助于Rational Robot也能够取得不错的效果。
  当然,成功开发J2EE应用的因素有很多。比如,Entity Beans的成功应用很大程度上与底层Database的设计有关系(如果表结构设计设计的不合理,将导致Entity Beans性能的急剧下降);如何最大化挖掘、提升团队各个成员的J2EE技能。等等这些,设计面很广。 (赛迪培训子网)
J2EE 探索者:用五个容易的步骤实现 JSP 自定义标记
JSP 自定义标记为在动态 Web 页中将表示与业务逻辑分离提供了一种标准化的机制,使页面设计者可以将注意力放到表示上,而应用程序开发人员编写后端的代码。在 J2EE 探索者 的这篇文章中,具有企业观念的开发者 Kyle Gabhart 介绍了 JSP 自定义标记的基本知识,并引导您完成将它们加入到 JSP 页面的五步过程。
您可能听说现在有上百种不同的方式,但是在开发 Web 应用程序时将表示逻辑与业务逻辑分离是很重要的。近年来,Java 平台已经发展为在体系结构层次上加入了这种分离。例如,在 JSP 体系结构中加入 JavaBean 组件使开发人员使用 JSP 标记获得和设置经过特别编码的 Java 组件上的属性。这些组件或者 JavaBean 再代表表示层执行后端业务处理。
JSP 自定义标记是 JSP/JavaBean 体系结构的产物。像 JavaBean 技术一样,自定义标记有助于将表示逻辑与业务逻辑分离。并且自定义标记成了 Web 设计者的 HTML、XML 和 Javascript 世界与软件工程师的 Java 代码、SQL 调用和算法世界之间的桥梁。
在本月的 J2EE 探索者 中,您将学到在 JSP 页中使用 JSP 自定义标记的一些基本知识。我们首先介绍 JSP 标记,然后直接进入创建标记、将它结合到 JSP 容器并在 JSP 页面中使用它的过程。在本文的最后,我们将简要讨论 Java 标准标记库(Java Standard Tag Library, JSTL),这是一组可以在您的 Java 开发项目中使用的、标准化的 JSP 自定义标记。
JSP 自定义标记
JSP 自定义标记 是用户定义的标记,它遵循 JSP JavaBean 标记(即 useBean、getProperty 和 setProperty)所使用的一种特殊的 XML 语法。当 servlet 容器处理自定义标记时,会调用一个或者多个 Java 类文件处理它,与用 Java 类文件处理 JSP 页面的 JavaBean 调用的方式基本一样。处理标记以后,容器将取其名字和属性、以及标记正文中可能有的任何内容,并将它传递给一个或者多个类文件进行处理。
Java 开发人员编写标记处理程序类以处理标记并处理所有需要的 Java 代码和数据操作。对于 Web 设计者来说,自定义标记与标准 HTML 标记除了都可以利用后端动态数据外,它们看上去与使用起来没什么区别。正确编写自定义标记可以让 Web 设计者创建、查询和操作数据而无需编写一行 Java 代码。正确使用自定义标记使 Java 开发人员不必再在编码过程中考虑表示层。这样应用程序开发小组的每一位成员都可以关注于他或者她最擅长的事物。
实现 JSP 自定义标记
JSP 体系结构需要以下组件以实现自定义标记:
在每一页中有一个 JSP 声明
Web 应用程序描述符(web.xml)中的一个项
一个包含特殊 XML 文件和为处理自定义标记而调用的 Java 类的 JAR 文件
在下面几节,您将一步一步地学习如何满足这些要求并将自定义标记加入到 JSP 页面中。要想成功实现 JSP 自定义标记,您需要采取下面五个步骤:
编写标记处理程序类。
创建标记库描述符(TLD)。
使 TLD 文件和处理程序类可访问。
引用标记库。
在 JSP 页面中使用标记。
这些内容是相当基本的,也不用花很长时间。就让我们开始吧。
第 1 步. 编写标记处理程序类
在下面的例子中,我们将使用一个非常简单的显示当前时间和日期的自定义标记例子。下面就是 DateTag:
<abc:displayDate />
我们要做的第一件事是编写标记处理程序类。在执行引用自定义标记的 JSP 页面时,JSP 容器判断每一个自定义标记。当容器遇到一个标记时,它调用与这个自定义标记相关联的标记处理程序,我们将在后面更多地讨论这个过程。然后,每一个标记处理程序实现 JSP API 中的一个特殊接口。标记有两种类型:可以处理标记内容(或者正文)的标记和不能处理标记内容的标记:
<abc:tagWithNoBody attribute="value"/>
<abc:tagWithBody attribute="value">
This is some body content that the tag handler can operate upon.
</abc:tagWithBody>
在 DateTag 例子中不需要加入正文内容,因为它只显示当前日期。因此,我们的处理程序类将实现 Tag 接口(一般是通过扩展 TagSupport 类)。如果我们要创建一个可以处理正文的标记,那么我们就需要实现 BodyTag 接口(一般是通过扩展 BodyTagSupport 类)。清单 1 显示了 DateTag 的处理程序类:
清单 1. 标记处理程序类
package myTags;
import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import javax.servlet.http.*;
import java.text.*;
import java.util.*;
public DateTag extends TagSupport {
public int doStartTag() throws javax.servlet.jsp.JspException {
HttpServletRequest req;
Locale locale;
HttpJspPage g;
DateFormat df;
String date;
JSPWriter out;

req = ( HttpServletRequest )pageContext.getRequest();
locale = req.getLocale();
df = SimpleDateFormat.getDateInstance(
SimpleDateFormat.FULL,locale );
date = df.format( new java.util.Date() );
try {
out = pageContext.getOut();
out.print( date );
} catch( IOException ioe ) {
throw new JspException( "I/O Error : " + ioe.getMessage() );
}//end try/catch
return Tag.SKIP_BODY;
}//end doStartTag()
}//end DateTag
关于这段代码的说明
关于 DateTag 处理程序类有几件事值得一说。首先看一下方法声明。如果我们直接实现 Tag 接口,那么就需要完成几个方法声明。因为 TagSupport 类是简单的、具体类,它完全实现了在 Tag 接口中声明的方法,我们可以只实现那些在自定义标记中要使用的方法。在这个简单的例子中,我们只实现了 doStartTag() 方法,它是在遇到开始标记时调用的。
您还可能注意到 doStartTag() 方法返回 SKIP_BODY。当然其原因是我们的简单日期标记没有正文。您要注意的最后一件重要的事情是使用了 pageContext 对象访问输出缓存以直接向输出流发送内容。您可能还记得在本系列以前的文章说过,pageContext 对象是一个隐式对象,它提供对与当前页面有关的属性的访问。
编写了源代码文件后,我们像编译所有其他 Java 类一样编译这个类(确保在类路径中加入 Servlet/JSP JAR 文件),然后将编译的类文件放到 Web 应用程序的类目录(WEB-INF/classes)中。如果我们开发的是几个标记或者定义有标记变量的标记,那么我们就会有多个标记处理程序类。在这种情况下我们可能选择将处理程序类打包在一个 JAR 文件中而不是使它们成为类目录中的分散的文件。
第 2 步. 创建 TLD
下一步是定义包含自定义标记与处理它的 Java 类(或多个类)之间的映射的库。这个库是在一个名为标记库描述符(TLD)的 XML 文档中定义的。我们将从 DateTag 例子 DateTagLib.tld 中调用这个 TLD。注意“.tld”是这种文件的标准扩展名。
清单 2. DateTagLib.tld 文件
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib>
<tlibversion>1.0</tlibversion>
<info>A simple tag library</info>
<tag>
<name>displayDate</name>
<tagclass>myTags.DateTag</tagclass>
<bodycontent>empty</bodycontent>
<info>Display Date</info>
</tag>
</taglib>
DateTagLib.tld 是一个出色的、最小的标记库描述符文件。所有关键信息都包含在 Tag 标记中,在这里映射了标记名和处理程序类,我们声明了标记对于正文内容的敏感性。对于更复杂的情况,我们可以使用其他的 XML 标记以提供有关库和标记的更多信息。在一个库中定义多个标记也很常见。
第 3 步. 使 TLD 和处理程序类可访问
第 3 步是使这个类或者这些类和 TLD 可以被 Web 应用程序访问。有两种方法:可以将类和 TLD 打包到一个 JAR 文件中,再将这个 JAR 文件储存在 Web 应用程序的 lib 目录中,也可以将类文件分散地放到 classes 子目录中并将 TLD 文件放到 Web 应用程序的 WEB-INF 目录下面的某一位置。
在这个例子中,我们将使用第二种方法,将 TLD 文件和类分散地放到 Web 应用程序目录结构中。您可以回忆起在第 1 步中我们已经将标记处理程序类放到了 classes 目录中,所以我们实际上只需储存 TLD 文件。TLD 文件被储存在 WEB-INF 目录或者子目录中,如果是部署 Java 文件,则储存在 JAR 的 META-INF/ 目录或者子目录。在这里,我们没有使用 JAR 文件,所以我们只将 TLD 储存到 Web 应用程序的 WEB-INF/lib 目录中。
第 4 步. 引用这个库
这时,我们已经编译了标记处理程序类、创建了 TLD 文件以定义处理程序类和标记之间的映射、并保证类和标记在应用程序中都是可访问的。下一步是建立 JSP 页面与标记库之间的引用。有两种方法声明 JSP 页面与其库之间的引用。可以通过 Web 应用程序描述符(web.xml)声明一个静态引用,也可以直接在页面中声明一个动态引用。我们将试用这两种方法。
为了进行静态引用,首先必须将下面的项加入到 web.xml 文件中:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<Web-app>
<!-- Define Servlets, Servlet Mappings, etc. -->
<taglib>
<taglib-uri>myTags</taglib-uri>
<taglib-location>/WEB-INF/lib/DateTagLib.tld</taglib-location>
</taglib>
</Web-app>
然后,将 JSP 声明加入到所有需要使用自定义标记库的页面中:
<%@ taglib uri="myTags" prefix="abc" %>
注意指定的 uri 属性与在 web.xml 文件中指定的 taglib-uri 值相匹配。
为了进行动态引用,只需在所有需要使用这个库的页面中加入一个 JSP 声明即可:
<%@ taglib uri="/WEB-INF/lib/DateTagLib.tld" prefix="abc" %>
静态引用与动态引用的比较
在进行标记库的静态引用时,JSP 声明必须查询 web.xml 文件以执行库查询。这意味着如果移动或者重命名了库,或者希望在 web.xml 文件中加入更多的库,就必须停止服务器、更新 web.xml 文件、然后重新启动服务器。动态方法让 JSP 页直接指向 TLD 位置,因而是在解释 JSP 页面时进行处理。
静态方法提供了页面与库的实际名和位置之间一定程度的非直接性,这可以为您提供一些改变这些属性而不修改页面的灵活性。另一方面,动态方法提供了更大的灵活性,让您可以在运行时增加和移动标记声明。如果您对动态方法感兴趣,但是又担心做了一些改变后、有可能要更新多个页面的维护负担,那么您可以始终将 JSP 声明放到一个单独的 JSP 文件中,并在每一个要访问 Web 应用程序的自定义库的页面中加入这一页。这使您具有在运行时只需要更新信息一次就可以增加库的灵活性。
第 5 步. 在 JSP 页面中使用标记
完成了所有这些准备工作后,我们就可以在 JSP 页面中使用这些自定义标记了。清单 3 显示了包含 DateTag 的 JSP 页面的浏览器输出:
清单 3. 带有自定义标记的 JSP 页
<%@ taglib uri="/WEB-INF/lib/DateTagLib.tld" prefix="abc" %>
<HTML>
<HEAD>
<TITLE>Date tag example</TITLE>
</HEAD>

<BODY>
<H1>Date tag Example</H1>
<p>Hi today is <b><abc:displayDate /></b> </p>
</BODY>
</HTML>
重新启动 Web 服务器并测试自己的 JSP 页面 !结果看起来类似于图 1 所示。
图 1. DateTag 的浏览器输出
用 JSTL 节省时间
您所需要的自定义标记功能中也许有多达百分之八十已经由 J2EE 团体创建并标准化了。使用现有的标记库而不是从头创建所有东西会使您节省大量时间和精力。尽管在公共域有数十种库,不过业界汇集了一个特定的自定义库。Java 标准标记库(JSTL)是由 Java Community Process 设计的,其参考实现是由 Apache Group 通过 Jakarta Taglibs 项目所开发和维护的(参阅参考资料)。
JSTL 定义了针对常见 Web 应用程序处理需求,如变量支持、流程控制、URL 管理、XML 操作、国际化、数据库访问等等的标记。除了一组丰富的标记外,JSTL 还定义了自己的表达式语言(EL)。EL 使我们可以容易地访问应用程序数据并更容易在不使用脚本或者请求时表达式的条件下操作这些数据。
除了节省您从头开发所有标记的时间和精力,JSTL 还具有标准化和业界承认的所有好处。这些好处包括厂商支持、大量介绍文字、以及有很大的机会找到具有 JSTL 经验的雇员或者承包商。
结束语
在 J2EE Web 开发中越来越多地需要将业务和表示逻辑分离,JSP 自定义标记提供了替代简单的老 JavaBean 和 Java 脚本的一个有吸引力的方法。更好的是在 JSTL 中已存在一组已定义的标准的自定义标记库。在 J2EE 探索者 的这篇文章中,您经历了从头创建一个自定义标记并在 JSP 页面中实现它的过程。我还简单介绍了 JSTL 并阐述了使用它而不是从头创建所有的自定义标记的好处。
下个月,我们将继续探索 J2EE 技术,对 Web 应用程序安全体系结构进行分析。祝这段时间里探索快乐!

[J2EE]项目艰辛笔记
这3天让Eclipse-Tocmat-Struts 的配置问题搞的一直头大,今天下班前终于将其搞定 :-)
我的做法是将Struts 配置到标准的J2EE工程里,具体为:将*.jar 放到WEB-INF/lib 下,编写
WEB-INF 下的struts-config.xml文件,将tld放到WEB-INF 下,配置web.xml 文件;
在发布的时候,将J2EE工程发布为标准的 war 文件,直接放到 $TOMCAT/webapps/ 下运行


1.struts-config.xml 文件的配置
STRUTS 配置中最重要的应该是struts-config.xml文件的配置了,
struts-config.xml 文件的作用是映射form bean && action bean ,其中最重要的是
<action-mappings> </action-mappings> 的映射,它定义了JSP<->FORM BEAN<->ACTION BEAN
之间的对应和forward 转发(在ACTION BEAN 里用到);值得注意的是:JSP 中text/password
等文本标签必须在其对应的FORM BEAN 中有getter/setter 方法,否则将提示出错
(花了2天才搞定!)

2.工程在TOMCAT 下的发布
标准的J2EE可以在ECLIPSE 中方便的进行开发,这中间,BEAN 和 SERVLET的单元测试也可以在
ECLIPSE 中进行,当一切似乎没什么问题时,你可以将其发布;值得注意的是,你应该让 ECLISPE
先为你编译,即将src 编译为.class 放到 WEB-INF/class 中,(花了1上午也没搞定,幸好ZHENGQ
帮忙),编译之后,就可用Lomboz 做发布了,这个东西会帮你将工程发布为.war 文件

3.依然存在的问题
1)整个过程非常麻烦,尤其是调试.jsp的时候,期待一种比较优雅高效的方式
2)使用lomboz发布时,应该可以指定目录,但现在还不知道
3)eclipse 的调试也比较繁,期待一种简洁的方式 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值