在本文中带领你学习已经实践和得到证实的性能调整技术它将大大地提高你的servlet和jsp页面的性能进而提升JEE的性能这些技术的部分用于开发阶段例如设计和编码阶段另一部分技术则与配置相关
技术在HttpServlet init()方法中缓存数据
服务器会在创建servlet实例之后和servlet处理任何请求之前调用servlet的init()方法该方法在servlet的生命周期中仅调用一次为了提高性能在init()中缓存静态数据或完成要在初始化期间完成的代价昂贵的操作例如一个最佳实践是使用实现了 javaxsqlDataSource接口的JDBC连接池DataSource从JNDI树中获得每调用一次SQL就要使用JNDI查找 DataSource是非常昂贵的工作而且严重影响了应用的性能Servlet的init()方法可以用于获取DataSource并缓存它以便之后的重用
以下是引用片段
public class ControllerServlet extends HttpServlet
{
private javaxsqlDataSource testDS = null;
public void init(ServletConfig config) throws ServletException
{
superinit(config);
Context ctx= null;
try
{
ctx = new InitialContext();
testDS = (javaxsqlDataSource)ctxlookup(jdbc/testDS);
}
catch(NamingException ne)
{
neprintStackTrace();
}
catch(Exception e)
{
eprintStackTrace();
}
}
public javaxsqlDataSource getTestDS()
{
return testDS;
}
}
技术禁用servlet和Jsp的自动装载功能
当每次修改了Servlet/JSP之后你将不得不重新启动服务器由于自动装载功能减少开发时间该功能被认为在开发阶段是非常有用的但是它在运行阶段是非常昂贵的;servlet/JSP由于不必要的装载增加类装载器的负担而造成很差的性能同样这会使你的应用由于已被某种类装载器装载的类不能和当前类装载器装载的类不能相互协作而出现奇怪的沖突现象因此在运行环境中为了得到更好的性能关闭servlet/JSP的自动装载功能
技术控制HttpSession
许多应用需要一系列客户端的请求因此他们能互相相关联由于HTTP协议是无状态的所以基于Web的应用需要负责维护这样一个叫做 session的状态为了支持必须维护状态的应用Java servlet技术提供了管理session和允许多种机制实现session的APIHttpSession对象扮演了session但是使用它需要成本无论何时HttpSession被使用和重写它都由servlet读取你可以通过使用下面的技术来提高性能
在JSP页面中不要创建默认的HttpSession:默认情况下JSP页面创建HttpSession如果你在JSP页面中不用HttpSession为了节省性能开销使用下边的页面指令可以避免自动创建HttpSession对象
以下是引用片段
< %@ page session=false%>
不要将大的对象图存储在HttpSession中如果你将数据当作一个大的对象图存储在HttpSession中应用服务器每次将不得不处理整个HttpSession对象这将迫使Java序列化和增加计算开销由于序列化的开销随着存储在HttpSession对象中数据对象的增大系统的吞吐量将会下降
用完后释放HttpSession当不在使用HttpSession时使用HttpSessioninvalidate()方法使sesion失效
设置超时值一个servlet引擎有一个默认的超时值如果你不删除session或者一直把session用到它超时的时候servlet引擎将把session从内存中删除由于在内存和垃圾收集上的开销session的超时值越大它对系统弹性和性能的影响也越大试着将session的超时值设置的尽可能低
技术使用gzip压缩
压缩是删除冗余信息的作法用尽可能小的空间描述你的信息使用gzip(GNU zip)压缩文档能有效地减少下载HTML文件的时间你的信息量越小它们被送出的速度越快因此如果你压缩了由你web应用产生的内容它到达用户并显示在用户屏幕上的速度就越快不是任何浏览器都支持gzip压缩的但检查一个浏览器是否支持它并发送gzip压缩内容到浏览器是很容易的事情下边的代码段说明了如何发送压缩的内容
以下是引用片段
public void doGet(HttpServletRequest request HttpServletResponse response)
throws IOException ServletException
{
OutputStream out = null
// Check the AcceptingEncoding header from the HTTP request
// If the header includes gzip choose GZIP
// If the header includes compress choose ZIP
// Otherwise choose no compression
String encoding = requestgetHeader(AcceptEncoding);
if (encoding != null && encodingindexOf(gzip) != )
{
responsesetHeader(ContentEncoding gzip);
out = new GZIPOutputStream(responsegetOutputStream());
}
else if (encoding != null && encodingindexOf(compress) != )
{
responsesetHeader(ContentEncoding compress);
out = new ZIPOutputStream(responsegetOutputStream());
}
else
{
out = responsegetOutputStream();
}
}
技术不要使用SingleThreadModel
SingleThreadModel保证servlet一次仅处理一个请求如果一个servlet实现了这个接口servlet引擎将为每个新的请求创建一个单独的servlet实例这将引起大量的系统开销如果你需要解决线程安全问题请使用其他的办法替代这个接口 SingleThreadModel在Servlet 中是不再提倡使用
技术使用线程池
servlet引擎为每个请求创建一个单独的线程将该线程指派给service()方法然后在service()方法执行完后删除该线程默认情况下servlet引擎可能为每个请求创建一个新的线程由于创建和删除线程的开销是很昂贵的于是这种默认行为降低了系统的性能我们可以使用线程池来提高性能根据预期的并发用户数量配置一个线程池设置好线程池里的线程数量的最小和最大值以及增长的最小和最大值起初servlet引擎创建一个线程数与配置中的最小线程数量相等的线程池然后servlet引擎把池中的一个线程指派给一个请求而不是每次都创建新的线程完成操作之后servlet引擎把线程放回到线程池中使用线程池性能可以显着地提高如果需要根据线程的最大数和增长数可以创建更多的线程
技术选择正确的包括机制
在JSP页面中有两中方式可以包括文件包括指令(< %@ include file=testjsp %>)和包括动作(< jsp:include page=testjsp flush=true />)包括指令在编译阶段包括一个指定文件的内容;例如当一个页面编译成一个servlet时包括动作是指在请求阶段包括文件内容;例如当一个用户请求一个页面时包括指令要比包括动作快些因此除非被包括的文件经常变动否则使用包括指令将会获得更好的性能(wwwliancom)
技术在useBean动作中使用合适的范围
使用JSP页面最强大方式之一是和JavaBean组件协同工作JavaBean使用< jsp:useBean>标签可以嵌入到JSP页面中语法如下
以下是引用片段
< jsp:useBean id=name scope=page|request|session|application class=
packageclassName type=typeName>
< /jsp:useBean>
scope属性说明了bean的可见范围scope属性的默认值是page你应该根据你应用的需求选择正确的范围否则它将影响应用的性能
例如如果你需要一个专用于某些请求的对象但是你把范围设置成了session那么那个对象将在请求结束之后还保留在内存中它将一直保留在内存中除非你明确地把它从内存中删除使session无效或session超时如果你没有选择正确的范围属性由于内存和垃圾收集的开销将会影响性能因此为对象设置合适的范围并在用完它们之后立即删除