??xml version="1.0" encoding="utf-8" standalone="yes"?>
调整JSP和servlet的一些非常实用的Ҏ(gu)Q它可你的servlet和JSP面响应更快Q扩展性更强。而且在用h增加的情况下Q系l负载会(x)呈现出^滑上长的势。在本文中,我将通过一些实际例子和配置Ҏ(gu)使得你的应用E序的性能有出人意料的提升。其中,某些调优技术是在你的编E工作中实现的。而另一些技术是与应用服务器的配|相关的? 在本文中Q我们将详细地描q怎样通过调整servlet和JSP面Q来提高你的应用E序的M性能。在阅读本文之前Q假设你有基本的servlet和JSP的知识?br />Ҏ(gu)一Q在servlet的initQ)(j)Ҏ(gu)中缓存数?/strong>
当应用服务器初始化servlet实例之后Qؓ(f)客户端请求提供服务之前,它会(x)调用q个servlet的initQ)(j)Ҏ(gu)。在一个servlet的生命周期中QinitQ)(j)Ҏ(gu)只会(x)被调用一ơ。通过在initQ)(j)Ҏ(gu)中缓存一些静态的数据或完成一些只需要执行一ơ的、耗时的操作,可大大地提高系l性能? 例如Q通过在initQ)(j)Ҏ(gu)中徏立一个JDBCq接池是一个最佳例子,假设我们是用jdbc2.0的DataSource接口来取得数据库q接Q在通常的情况下Q我们需要通过JNDI来取得具体的数据源。我们可以想象在一个具体的应用中,如果每次SQLh都要执行一ơJNDI查询的话Q那pȝ性能会(x)急剧下降。解x法是如下代码Q它通过~存DataSourceQ得下一ơSQL调用时仍然可以l利用它Q?br />public class ControllerServlet extends HttpServlet { private javax.sql.DataSource testDS = null; public void initQServletConfig configQ?throws ServletException { super.initQconfigQ? Context ctx = null; try { ctx = new InitialContextQ)(j); testDS = Qjavax.sql.DataSourceQctx.lookupQ?#8220;jdbc/testDS”Q? } catchQNamingException neQ?{ ne.printStackTraceQ)(j); } catchQException eQ?{ e.printStackTraceQ)(j); } } public javax.sql.DataSource getTestDSQ)(j) { return testDS; } ?. ?. }QnextpageQ?br />Ҏ(gu) 2Q禁止servlet和JSP 自动重蝲Qauto-reloadingQ?/strong>
Servlet/JSP提供了一个实用的技术,卌动重载技术,它ؓ(f)开发h员提供了一个好的开发环境,当你改变servlet和JSP面后而不必重启应用服务器。然而,q种技术在产品q行阶段对系l的资源是一个极大的损耗,因ؓ(f)它会(x)lJSP引擎的类装蝲器(classloaderQ带来极大的负担。因此关闭自动重载功能对pȝ性能的提升是一个极大的帮助?br />Ҏ(gu) 3Q?不要滥用HttpSession
在很多应用中Q我们的E序需要保持客L(fng)的状态,以便面之间可以怺联系。但不幸的是׃HTTPh天生无状态性,从而无法保存客L(fng)的状态。因此一般的应用服务器都提供了session来保存客L(fng)状态。在JSP应用服务器中Q是通过HttpSession对像来实现session的功能的Q但在方便的同时Q它也给pȝ带来了不的负担。因为每当你获得或更新sessionӞpȝ者要对它q行Ҏ(gu)的序列化操作。你可以通过对HttpSession的以下几U处理方式来提升pȝ的性能Q?/p>
如果没有必要Q就应该关闭JSP面中对HttpSession的缺省设|:(x) 如果你没有明指定的话,每个JSP面都会(x)~省地创Z个HttpSession。如果你的JSP中不需要用session的话Q那可以通过如下的JSP面指示W来止它:(x) Q?@ page session=“false”%Q?/p>
不要在HttpSession中存攑֤的数据对像:(x)如果你在HttpSession中存攑֤的数据对像的话,每当对它q行dӞ应用服务器都对其进行序列化Q从而增加了pȝ的额外负担。你在HttpSession中存攄数据对像大Q那pȝ的性能׃降得快? 当你不需要HttpSessionӞ快地释攑֮Q当你不再需要sessionӞ你可以通过调用HttpSession.invalidateQ)(j)Ҏ(gu)来释攑֮?/p>
量session的超时时间设得短一点:(x)在JSP应用服务器中Q有一个缺省的session的超时时间。当客户在这个时间之后没有进行Q何操作的话,pȝ?x)将相关的session自动从内存中释放。超时时间设得越大,pȝ的性能׃(x)低Q因此最好的Ҏ(gu)是量使得它的g持在一个较低的水^?br />Ҏ(gu) 4Q?页面输行压~?/strong>
压羃是解x据冗余的一个好的方法,特别是在|络带宽不够发达的今天。有的浏览器支持gzipQGNU zipQ进行来对HTML文gq行压羃Q这U方法可以戏剧性地减少HTML文g的下载时间? 因此Q如果你servlet或JSP面生成的HTML面q行压羃的话Q那用户׃(x)觉得面览速度?x)非常快。但不幸的是Q不是所有的览器都支持gzip压羃Q但你可以通过在你的程序中(g)查客L(fng)览器是否支持它。下面就是关于这U方法实现的一个代码片D:(x) public void doGetQHttpServletRequest requestQ?HttpServletResponse responseQ?throws IOExceptionQ?ServletException { OutputStream out = null String encoding = request.getHeaderQ?#8220;Accept-Encoding”Q? if Qencoding Q? null && encoding.indexOfQ?#8220;gzip”Q?Q? -1Q?{ request.setHeaderQ?#8220;Content-Encoding” Q?“gzip”Q? out = new GZIPOutputStreamQrequest.getOutputStreamQ)(j)Q? } else if Qencoding Q? null && encoding.indexOfQ?#8220;compress”Q?Q? -1Q?{ request.setHeaderQ?#8220;Content-Encoding” Q?“compress”Q? out = new ZIPOutputStreamQrequest.getOutputStreamQ)(j)Q? } else { out = request.getOutputStreamQ)(j); } ?. ?. }QnextpageQ?br />Ҏ(gu) 5Q?使用U程?/strong>
应用服务器缺省地为每个不同的客户端请求创Z个线E进行处理,qؓ(f)它们分派serviceQ)(j)Ҏ(gu)Q当serviceQ)(j)Ҏ(gu)调用完成后,与之相应的线E也随之撤消。由于创建和撤消U程?x)耗费一定的pȝ资源Q这U缺省模式降低了pȝ的性能。但所q的是我们可以通过创徏一个线E池来改变这U状c(din)? 另外Q我们还要ؓ(f)q个U程池设|一个最线E数和一个最大线E数。在应用服务器启动时Q它?x)创建数量等于最线E数的一个线E池Q当客户有请求时Q相应地从池从取Z个线E来q行处理Q当处理完成后,再将U程重新攑օ到池中。如果池中的U程不够地话Q系l会(x)自动地增加池中线E的数量Q但总量不能过最大线E数。通过使用U程池,当客L(fng)h急剧增加Ӟpȝ的负载就?x)呈现的qx的上升曲U,从而提高的pȝ的可伸羃性?br />Ҏ(gu) 6Q?选择正确的页面包含机?/strong>
在JSP中有两种Ҏ(gu)可以用来包含另一个页?1、用include指示W(Q?@ includee file=”test.jsp” %Q)(j)?2、用jsp指示W(Qjsp:includee page=”test.jsp” flush=”true”/Q)(j)?在实际中我发玎ͼ如果使用W一U方法的话,可以使得pȝ性能更高?br />Ҏ(gu) 7Q正地定javabean的生命周?/strong>
JSP的一个强大的地方是对javabean的支持。通过在JSP面中用<jsp:useBeanQ标{,可以javabean直接插入C个JSP面中。它的用方法如下:(x)
Qjsp:useBean id=“name” scope=“page|request|session|application” class= “package.className” type=“typeName”Q</jsp:useBeanQ?其中scope属性指Zq个bean的生命周期。缺省的生命周期为page。如果你没有正确地选择bean的生命周期的话,它将影响pȝ的性能?br />举例来说Q如果你只想在一ơ请求中使用某个beanQ但你却这个bean的生命周期设|成了sessionQ那当这ơ请求结束后Q这个bean仍然保留在内存中,除非session时或用户关闭浏览器。这样会(x)耗费一定的内存Qƈ无谓的增加了JVM垃圾攉器的工作量。因此ؓ(f)bean讄正确的生命周期,q在bean的命结束后快地清理它们,?x)用系l性能有一个提高? 其它一些有用的Ҏ(gu) 在字W串q接操作中尽量不使用“Q?#8221;操作W:(x)在java~程中,我们常常使用“Q?#8221;操作W来几个字W串q接hQ但你或总来没有想到过它居然会(x)对系l性能造成影响吧?׃字符串是帔RQ因此JVM?x)生一些(f)时的对像。你使用?#8220;Q?#8221;多Q生成的临时对像p多,q样也会(x)l系l性能带来一些媄(jing)响。解决的Ҏ(gu)是用StringBuffer对像来代?#8220;Q?#8221;操作W?/p>
避免使用System.out.printlnQ)(j)Ҏ(gu)Q由于System.out.printlnQ)(j)是一U同步调用,卛_调用它时Q磁盘I(y)/O操作必须{待它的完成Q因此我们要量避免对它的调用。但我们在调试程序时它又是一个必不可的方便工具Qؓ(f)了解册个矛盾,我徏议你最好用Log4j工具Q?span style="margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-family: inherit; vertical-align: baseline; color: #ff0000;">http://Jakarta.apache.org; Q,它既可以方便调试Q而不?x)生System.out.printlnQ)(j)q样的方法?/p>
ServletOutputStream ?PrintWriter的权衡:(x)使用PrintWriter可能?x)带来一些小的开销Q因为它?yu)所有的原始输出都{换ؓ(f)字符来输出Q因此如果用它来作为页面输出的话,pȝ要负担一个{换过E。而用ServletOutputStream作ؓ(f)面输出的话׃存在一个问题,但它是以二进制进行输出的。因此在实际应用中要权衡两者的利弊?/p>
@Autowired 与@Resource的区别:(x)
1?nbsp;@Autowired与@Resource都可以用来装配bean. 都可以写在字D上,或写在setterҎ(gu)上?/span>
2?nbsp;@Autowired默认按类型装配(q个注解是属业spring的)(j)Q默认情况下必须要求依赖对象必须存在Q如果要允许null|可以讄它的required属性ؓ(f)falseQ如Q@Autowired(required=false) Q如果我们想使用名称装配可以l合@Qualifier注解q行使用Q如下:(x)
3、@ResourceQ这个注解属于J2EE的)(j)Q默认安装名U进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字D上Ӟ默认取字D名q行安装名称查找Q如果注解写在setterҎ(gu)上默认取属性名q行装配。当找不C名称匚w的bean时才按照cdq行装配?span style="color: #ff0000;">但是需要注意的是,如果name属性一旦指定,只?x)按照名U进行装配?/span>
推荐使用Q@Resource注解在字D上Q这样就不用写setterҎ(gu)了,q且q个注解是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅?/span>
q里举个单的例子Q以供参考:(x)
比如我要数据写成下面的样子Q?/p>
1 | 2 | 3 | 4
5 | 6 | 8 | 9
也许看v来很单的Q因为每个数据所代表的长度是不一L(fng)Q也有可能编码不一P所有在你看来很单的事情׃应那么容易实C。必要每一个竖U和他下面的竖线是对其的?/p>
q里׃再将写数据的q程提出来了Q重Ҏ(gu)让每一列的数据都能有一个同L(fng)宽度Q?/p>
q样做,有个问题Q就是怎么定length的长度ؓ(f)多少合适呢Q?/p>
如果数据是从数据库中查找出来的,那么取数据库中q个字段的最大长度即可。如果是从文件中d的,那么最好就是遍历一下整个文Ӟ从中获取每个字段的最大长度?/p>
最后将Ҏ(gu)q回的str用输出流写入到文件中Q换行的话用out.write(lineSeparator)卛_?nbsp;
解析的工L(fng)l承org.xml.sax.helpers.DefaultHandlerQ然后覆盖父cȝ几个Ҏ(gu)卛_。方法的详细解释可以参照JDK的API文档?/p>
下面是一个实例:(x)
上面代码中,parser()是主Ҏ(gu)Q调用完此方法之后,可以调用getUrlPatternList()Ҏ(gu)获取Cweb.xml中解析出来的url-pattern节点的|security-constraint/web-resource-collection/url-patternQ?/p>
另外Q取元素的属性|可以在startElement()Ҏ(gu)中用attributes.getValue("<属性名>")获取到?/p>