??xml version="1.0" encoding="utf-8" standalone="yes"?> 首先去http://www.andykhan.com/jexcelapi/index.html下蝲最新的JExcelApi,把jxl.jar|于你的classpath中?/p>
写一个javaBean,利用JExcelApi来动态生成excel文档Q我q里写一个最单的Q示意性的。复杂的你可能还要查询数据库什么的?/p>
///////////////////////////Test.java/////////////////////////////////////////// public class Test{ //最好写一个这LmainҎ来测试一下你的这个class是否写好了?br />
public static void main(String[] args)throws Exception{ 写一个jsp,来利用Testq个javabean输出excel文档?/p>
///////////////////////////test_excel.jsp////////////////////////// Q?@page import="com.jagie.test.Test" %Q?br />
Q? q样大功告成了Q你用ie讉Ktest_excel.jspp在ie里面打开动态生成的excel文档了。一点ؕ码也没有?br />
q有Z怼?我在jsp开头加上<%@page contentType="application/vnd.ms-excel;charset=GBK" %Q这一句,Lresponse.setContentType("application/vnd.ms-excel");行不?回答q个问题很简单,是查看jsp服务器编译jsp后生成的java代码Q如果改成这P我的welogic7~译test_excel.jsp后生成的java文g的示意性代码是q样? public void _jspService(javax.servlet.http.HttpServletRequest request, // declare and set well-known variables: Object page = this; response.setHeader("Content-Type", "application/vnd.ms-excel; charset=GBK"); javax.servlet.http.HttpSession session = request.getSession(true); try { // error page try block //before final close brace... 很明显,屏蔽response.setContentType("application/vnd.ms-excel");后,在Test.writeExcel(response.getOutputStream());之前Qresponse.reset(); 之后没有讄response contenttype的正类型,当然输出Zؕ码了。而正输出excel的jsp的编译后源码是这L: public void _jspService(javax.servlet.http.HttpServletRequest request, Object page = this; out = pageContext.getOut(); javax.servlet.http.HttpSession session = request.getSession(true); try { // error page try block //before final close brace... 大家可以看到在response.reset();之后,Test.writeExcel(response.getOutputStream());之前正确的设|了response的输出内宏V所以输出就正常了?/p>
最后,希望q篇文章能对你有所启发,如有错误之处Q敬h评指? 一、web.xml文g <web-app> <filter-mapping> <listener> </web-app> 二、既是ServletContextListener又是 HttpSessionListener监听器ClickstreamLoggerc?/p>
import java.io.IOException; import javax.servlet.*; import javax.servlet.http.*; public class ClickstreamFilter implements Filter { protected FilterConfig filterConfig; private final static String FILTER_APPLIED = "_clickstream_filter_applied"; public void init(FilterConfig config) throws ServletException { this.filterConfig = filterConfig; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 保该过滤器在每ơ请求中只被使用一?O:P> if (request.getAttribute(FILTER_APPLIED) == null) { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); HttpSession session = ((HttpServletRequest)request).getSession(); Clickstream stream = (Clickstream)session.getAttribute("clickstream"); stream.addRequest(((HttpServletRequest)request)); } // 传递请?O:P> chain.doFilter(request, response); } public void destroy() { } } doFilter ()Ҏ取得用户的sessionQ从中获取ClickstreamQƈ当前请求数据加到Clickstream中。其中用了一个特D的 FILTER_APPLIED标记属性来标注此过滤器是否已经被当前请求用(可能会在h调度中发生)q且忽略所有其他的qo器行为?O:P> Servlet是一U独立于q_和协议的服务器端的Java应用E序Q可以生成动态的Web面 一、概q?/p>
Servlet是一U独立于q_和协议的服务器端的Java应用E序Q可以生成动态的Web面? Servlet是位于Web 服务器内部的服务器端的Java应用E序Q与传统的从命o行启动的Java应用E序不同QServlet由Web服务器进行加载,该Web服务器必d含支持Servlet的Java虚拟机? Java Servlet ?Applet 的比? 怼之处Q?/p>
* 它们不是独立的应用程序,没有main()Ҏ?/p>
* 它们不是qhE序员调用,而是由另外一个应用程?容器)调用?/p>
* 它们都有一个生存周期,包含init()和destroy()Ҏ?/p>
不同之处Q?/p>
* Appleth很好的图形界?AWT)Q与览器一P在客Lq行?/p>
* Servlet 则没有图形界面,q行在服务器端?/p>
Java Servlet ?CGI(Common Gateway Interface) 的比? 与传l的CGI和许多其他类似CGI的技术相比,Java Servleth更高的效率,更容易用,功能更强大,h更好的可UL性,更节省投资。在未来的技术发展过E中QServlet有可能彻底取代CGI?/p>
* 高效 在传l的CGI中,每个h都要启动一个新的进E,如果CGIE序本n的执行时间较短,启动q程所需要的开销很可能反而超q实际执行时间。而在Servlet中,每个h׃个轻量的JavaU程处理(而不是重量的操作系l进E?? 在传lCGI中,如果有N个ƈ发的对同一CGIE序的请求,则该CGIE序的代码在内存中重复装载了Nơ;而对于ServletQ处理请求的是N个线E,只需要一份ServletcM码。在性能优化斚wQServlet也比CGI有着更多的选择?/p>
* 方便 Servlet提供了大量的实用工具例程Q例如自动地解析和解码HTML表单数据、读取和讄HTTP头、处理Cookie、跟t会话状态等?/p>
* 功能强大 在Servlet中,许多使用传统CGIE序很难完成的Q务都可以L地完成。例如,Servlet能够直接和Web服务器交互,而普通的CGIE序不能。Servletq能够在各个E序之间׃n数据Q得数据库q接池之cȝ功能很容易实现?/p>
* 可移植性好 Servlet用Java~写QServlet APIh完善的标准。因此,为IPlanet Enterprise Server写的Servlet无需M实质上的改动卛_UL到Apache、Microsoft IIS或者WebStar。几乎所有的L服务器都直接或通过插g支持Servlet?/p>
* 节省投资 不仅有许多廉L臛_费的Web服务器可供个人或规模网站用,而且对于现有的服务器Q如果它不支持Servlet的话Q要加上q部分功能也往往是免费的(或只需要极的投资)?/p>
Java Servlet ?JSP(JavaServer Pages) 的比? JavaServer Pages(JSP)是一U实现普通静态HTML和动态HTML混合~码的技术,JSPq没有增加Q何本质上不能用Servlet实现的功能。但是,在JSP中编写静态HTML更加方便Q不必再用println语句来输出每一行HTML代码。更重要的是Q借助内容和外观的分离Q页面制作中不同性质的Q务可以方便地分开Q比如,由页面设计者进行HTML设计Q同时留ZServletE序员插入动态内容的I间?/p>
Java Servlet API 2.2 ?/p>
Java Servlet API 2.2 的类和接口组成两个Java 包,卻Ijavax.servlet ?javax.servlet.http(q包括javax.servlet.jsp包,不在本篇文章讨论范围之内)?/p>
javax.servlet 包提供了控制 Servlet 生命周期所必需?Servlet 接口Q是~写 Servlet 时必要实现的?/p>
javax.servlet.http 包提供了从Servlet 接口z出的专门用于处理 HTTP h的抽象类和一般的工具cR所有的Servlet 对象都要实现Servlet 接口Q大多数情况下是作ؓ已经实现了Servlet 接口的javax.servlet.GenericServlet ?javax.servlet.http.HttpServlet q两个抽象类的子cL间接实现Servlet 接口?/p>
javax.servlet 包定义的cd接口Q?/strong> interface RequestDispatcher //定义一U对象,用于从客h受请求,q将h发送到服务器上M指定的资源,如一个Servlet 、JSP ?HTML 文g?/p>
interface Servlet //定义了所?Servlet 必须实现的方法?/p>
interface ServletConfig //定义Servlet config 对象Q由Servlet 引擎用在 Servlet 初始化时Q向 Servlet 传递信息?/p>
interface ServletContext //定义了一pdҎQ以便Servlet与其q行的环境通信?/p>
interface ServletRequest //定义了用于向Servlet传递客戯求信息的对象?/p>
interface ServletResponse //定义了一个对象,由Servlet用于向客户发送响应?/p>
interface SingleThreadModel //用于保证Servlet在Q一时刻Q只处理一个请求?/p>
class GenericServlet //l承Servlet接口Q定义了一个通用的,与协议无关的Servlet?/p>
class ServletInputStream //定义了一个输入流Q用于由Servlet从中d客户h的二q制数据?/p>
class ServletOutputStream //定义了一个输出流Q用于由Servlet向客户发送二q制数据?/p>
class ServletException //定义了一个当Servlet遇到问题时可以抛出的异常?/p>
class UnavailableException //定义了一U异常,用于由Servlet指明它永q或暂时不可用?/p>
javax.servlet.http 包定义的cd接口Q?/strong> interface HttpServletRequest //l承了ServletRequest 接口QؓHTTPServlet 提供h信息?/p>
interface HttpServletResponse //l承了ServletResponse 接口QؓHTTPServlet 输出响应信息提供支持?/p>
interface HttpSession //为维?HTTP 用户的会话状态提供支持?/p>
interface HttpSessionBindingListener //使得某对象在加入一个会话或从会话中删除时能够得到通知?/p>
interface HttpSessionContext //由Servlet 2.1 定义Q该对象在新版本已不被支持?/p>
class Cookie //用在Servlet 中用Cookie 技?/p>
class HttpServlet //定义了一个抽象类Q?GenericServlet 抽象c,应被 HTTPServlet l承?/p>
class HttpSessionBindingEvent //定义了一U对象,当某一个实CHttpSessionBindingListener接口的对象被加入会话或从?/话中删除Ӟ会收到该cd象的一个句?/p>
class HttpUtils //提供了一pd便于~写HTTPServlet 的方法?/p>
下面主要介绍javax.servlet.http提供的HTTP Servlet应用~程接口? HTTP Servlet 使用一?HTML 表格来发送和接收数据。要创徏一?HTTP ServletQ请扩展 HttpServlet c, 该类是用专门的方法来处理 HTML 表格?GenericServlet 的一个子cR?HTML 表单是由 <FORM> ?</FORM> 标记定义的。表单中典型地包含输入字D?如文本输入字Dc复选框、单选按钮和选择列表)和用于提交数据的按钮。当提交信息Ӟ它们q指定服务器应执行哪一个Servlet(或其它的E序)?HttpServlet cd?init()、destroy()、service() {方法。其?init() ?destroy() Ҏ是承的? (1) init() Ҏ ?Servlet 的生命期中,仅执行一?init() Ҏ。它是在服务器装?Servlet 时执行的?可以配置服务器,以在启动服务器或客户机首ơ访?Servlet 时装?Servlet?无论有多客h讉K ServletQ都不会重复执行 init() ? ~省?init() Ҏ通常是符合要求的Q但也可以用定制 init() Ҏ来覆盖它Q典型的是管理服务器端资源?例如Q可能编写一个定?init() 来只用于一ơ装?GIF 囑փQ改q?Servlet q回 GIF 囑փ和含有多个客hh的性能。另一个示例是初始化数据库q接。缺省的 init() Ҏ讄?Servlet 的初始化参数Qƈ用它?ServletConfig 对象参数来启动配|, 因此所有覆?init() Ҏ?Servlet 应调?super.init() 以确保仍然执行这些Q务。在调用 service() Ҏ之前Q应保已完成了 init() Ҏ? (2) service() Ҏ service() Ҏ?Servlet 的核心。每当一个客戯求一个HttpServlet 对象Q该对象的service() Ҏp被调用,而且传递给q个Ҏ一?h"(ServletRequest)对象和一?响应"(ServletResponse)对象作ؓ参数??HttpServlet 中已存在 service() Ҏ。缺省的服务功能是调用与 HTTP h的方法相应的 do 功能。例如, 如果 HTTP hҎ?GETQ则~省情况下就调用 doGet() 。Servlet 应该?Servlet 支持?HTTP Ҏ覆盖 do 功能。因?HttpServlet.service() Ҏ会检查请求方法是否调用了适当的处理方法,不必要覆?service() Ҏ。只需覆盖相应?do Ҏ可以了? 当一个客户通过HTML 表单发出一个HTTP POSThӞdoPost()Ҏ被调用。与POSTh相关的参CZ个单独的HTTP h从浏览器发送到服务器。当需要修Ҏ务器端的数据Ӟ应该使用doPost()Ҏ? 当一个客户通过HTML 表单发出一个HTTP GETh或直接请求一个URLӞdoGet()Ҏ被调用。与GETh相关的参数添加到URL的后面,q与q个h一起发送。当不会修改服务器端的数据时Q应该用doGet()Ҏ? Servlet的响应可以是下列几种cdQ? 一个输出流Q浏览器Ҏ它的内容cd(如text/HTML)q行解释? 一个HTTP错误响应, 重定向到另一个URL、servlet、JSP? (3) destroy() Ҏ destroy() Ҏ仅执行一ơ,卛_服务器停止且卸装Servlet 时执行该Ҏ。典型的Q将 Servlet 作ؓ服务器进E的一部分来关闭。缺省的 destroy() Ҏ通常是符合要求的Q但也可以覆盖它Q典型的是管理服务器端资源。例如,如果 Servlet 在运行时会篏计统计数据,则可以编写一?destroy() ҎQ该Ҏ用于在未装入 Servlet 时将l计数字保存在文件中。另一个示例是关闭数据库连接? 当服务器卸装 Servlet Ӟ在所?service() Ҏ调用完成后,或在指定的时间间隔过后调?destroy() Ҏ。一个Servlet 在运行service() Ҏ时可能会产生其它的线E,因此L认在调用 destroy() ҎӞq些U程已终止或完成? (4) GetServletConfig()Ҏ GetServletConfig()Ҏq回一?ServletConfig 对象Q该对象用来q回初始化参数和ServletContext。ServletContext 接口提供有关servlet 的环境信息? (5) GetServletInfo()Ҏ GetServletInfo()Ҏ是一个可选的ҎQ它提供有关servlet 的信息,如作者、版本、版权? 当服务器调用sevlet 的Service()、doGet()和doPost()q三个方法时Q均需?"h"?响应"对象作ؓ参数?h"对象提供有关h的信息,?响应"对象提供了一个将响应信息q回l浏览器的一个通信途径?/p>
javax.servlet 软g包中的相关类为ServletResponse和ServletRequestQ而javax.servlet.http 软g包中的相关类为HttpServletRequest ?HttpServletResponse? Servlet 通过q些对象与服务器通信q最l与客户机通信。Servlet 能通过调用"h"对象的方法获知客h环境Q服务器环境的信息和所有由客户机提供的信息。Servlet 可以调用"响应"对象的方法发送响应,该响应是准备发回客户机的?/p>
q行Servlet开发所需要的基本环境是JSDK以及一个支持Servlet的Web服务?/span> ~写Servlet所需要的开发环?/strong> 希尔排序法基本思想是:取一个间隔,长序列分成若干短的子序列,Ҏ个子序列q行直插排序Q然后逐渐~小间隔Q重复以上过E,直到间隔? 前面我们学习了两U插入排序法,但当要排序的数组长度长q且数D不成序,比较和交换的ơ数p?效率低。因此D.L.Shell?959q提Z~小增量排序法(又叫希尔排序法)Q基本思想是:取一个间隔,长序列分成若干短的子序列,Ҏ个子序列q行直插排序Q然后逐渐~小间隔Q重复以上过E,直到间隔?。可以看到这U算法,较好的克服了直接插入排序法的不?br />
使用Java Servlet API q行会话理
word面只要在jsp头设|如下指令:
<%@page contentType="application/msword;charset=GBK" %>
excel如下Q?br />
<%@page contentType="application/vnd.ms-excel;charset=GBK" %>
]]>
]]>问题Qservlet在不写端口号?讉K不到Q?04Q,写端口号可以访?/pre>
解决办法Q?/pre>
? http.conf文g?
JkMount /servlet/* ajp13
改ؓ
JkMount /* ajp13
p么简单!
http://book.77169.org/ask25/how173515.htm
]]>
<input type="text" />在页面传中文旉要处理否则可能会出现qQ?lt;input type="hidden" />不用作中文处理!
真是奇妙Q!Q!Q?br />
另附Qjsp 中文q处理代码一Dc?br />
String str = new String(request.getParameter("name").getBytes("ISO-8859-1"));
]]>
]]>
最q在|上看到一个用java来操Uexcel的open source,在weblogic上试用了一?觉得很不?Ҏ向大家推荐一下?/p>
package com.jagie.test;
import java.io.*;
import jxl.*;
import jxl.write.*;
import jxl.format.*;
import java.util.*;
import java.awt.Color;
public static void writeExcel(OutputStream os) throws Exception {
jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(os);
jxl.write.WritableSheet ws = wwb.createSheet("TestSheet1", 0);
jxl.write.Label labelC = new jxl.write.Label(0, 0, "我爱中国");
ws.addCell(labelC);
jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL,20, WritableFont.BOLD, false,
UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.GREEN);
jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc);
wcfFC.setBackground(jxl.format.Colour.RED);
labelC = new jxl.write.Label(6, 0, "中国爱我",wcfFC);
ws.addCell(labelC);
//写入Exel工作?br />
wwb.write();
//关闭Excel工作薄对?br />
wwb.close();
}
File f=new File("kk.xls");
f.createNewFile();
writeExcel(new FileOutputStream(f));
}
}
response.reset();
response.setContentType("application/vnd.ms-excel");
Test.writeExcel(response.getOutputStream());
%Q?
------------------------------------------------------------
[正文] 2?nbsp;
也许有h会问:response.reset();可不可以不要q一?我的是一定要写,除非你能保证response的buffer里面没有别的东西?/p>
javax.servlet.http.HttpServletResponse response) throws java.io.IOException,
javax.servlet.ServletException {
javax.servlet.ServletConfig config = getServletConfig();
javax.servlet.ServletContext application = config.getServletContext();
javax.servlet.jsp.tagext.Tag _activeTag = null;
// variables for Tag extension protocol
javax.servlet.jsp.JspWriter out;
javax.servlet.jsp.PageContext pageContext =
javax.servlet.jsp.JspFactory.getDefaultFactory().getPageContext(this,
request, response, null, true, 8192, true);
out = pageContext.getOut();
JspWriter _originalOut = out;
response.setContentType("application/vnd.ms-excel;charset=GBK");
out.print("\r\n\r\n\r\n\r\n");
out.print("\r\n");
//[ /test_excel.jsp; Line: 6]
response.reset(); //[ /test_excel.jsp; Line: 7]
//response.setContentType("application/vnd.ms-excel");
//[ /test_excel.jsp; Line: 8]
Test.writeExcel(response.getOutputStream()); //[ /test_excel.jsp; Line: 9]
} catch (Throwable __ee) {
while (out != null && out != _originalOut) out = pageContext.popBody();
((weblogic.servlet.jsp.PageContextImpl)pageContext).handlePageException((Throwable)__ee);
}
}
javax.servlet.http.HttpServletResponse response) throws java.io.IOException,
javax.servlet.ServletException
{
// declare and set well-known variables:
javax.servlet.ServletConfig config = getServletConfig();
javax.servlet.ServletContext application = config.getServletContext();
javax.servlet.jsp.tagext.Tag _activeTag = null;
// variables for Tag extension protocol
javax.servlet.jsp.JspWriter out;
javax.servlet.jsp.PageContext pageContext =
javax.servlet.jsp.JspFactory.getDefaultFactory().getPageContext(this, request, response, null, true, 8192, true);
JspWriter _originalOut = out;
out.print("\r\n");
//[ /test_excel.jsp; Line: 2]
response.reset(); //[ /test_excel.jsp; Line: 3]
response.setContentType("application/vnd.ms-excel"); //[ /test_excel.jsp; Line: 4]
Test.writeExcel(response.getOutputStream()); //[ /test_excel.jsp; Line: 5]
} catch (Throwable __ee) {
while (out != null && out != _originalOut) out = pageContext.popBody();
((weblogic.servlet.jsp.PageContextImpl)pageContext).handlePageException((Throwable)__ee);
}
}
]]>
看了|上一译文《Servlet 2.3 qo器编E》原?《Filter code with Servlet 2.3 model 》出自http://www.javawold.com/。里面讲了四个例子,有三个意思不大,没有仔细看?
下面q个qo器示例跟t用戯求,向网l管理员报告谁在她的|站上以及每个用h在访问那个页面?font face="宋体">试l果囑֦下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<!-- CLICKSTREAM LOGGER -->
<filter>
<filter-name>clickstreamFilter</filter-name>
<filter-class>com.java3z.examples.ClickstreamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>clickstreamFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-name>clickstreamFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<listener-class>com.java3z.examples.ClickstreamLogger</listener-class>
</listener>
<!-- END CLICKSTREAM LOGGER -->
q注册了ClickstreamFilterq设|其处理*.jsp?.html来的h。这也将ClickstreamLogger注册Z个监听器以在应用事g发生时接受他们?package com.java3z.examples;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ClickstreamLogger implements ServletContextListener, HttpSessionListener
{
Map clickstreams = new HashMap();
public ClickstreamLogger()
{
// System.out.println("ClickstreamLogger constructed");
}
public void contextInitialized(ServletContextEvent sce)
{
// System.out.println("ServletContext Initialised");
sce.getServletContext().setAttribute("clickstreams", clickstreams);
}
public void contextDestroyed(ServletContextEvent sce)
{
sce.getServletContext().setAttribute("clickstreams", null);
// System.out.println("ServletContext Destroyed");
}
public void sessionCreated(HttpSessionEvent hse)
{
// System.out.println("Session Created");
HttpSession session = hse.getSession();
Clickstream clickstream = new Clickstream();
session.setAttribute("clickstream", clickstream);
clickstreams.put(session.getId(), clickstream);
}
public void sessionDestroyed(HttpSessionEvent hse)
{
// System.out.println("Session Destroyed");
HttpSession session = hse.getSession();
Clickstream stream = (Clickstream)session.getAttribute("clickstream");
clickstreams.remove(session.getId());
System.out.println("Final session clickstream:\n" + stream);
}
}
ClickstreamLoggercdservlet环境创徏时设|全局属性getServletContext.setAttribute("clickstreams", clickstreams),一?br />
Map,在用戯问网站时讄会话属性session.setAttribute("clickstream", clickstream),q将可记录会话数据的对象clickstream
攑օMap,以便在JSP面中输出网站访问者的信息?br />
三、过滤器ClickstreamFilterc?br />
package com.java3z.examples;
四、保存请求数据的Clickstreamc?br />
package com.java3z.examples;
五、是机器人吗Q?br />
import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Clickstream implements Serializable
{
List clickstream = new ArrayList();
String hostname = null;
HttpSession session = null;
String initialReferrer = null;
Date start = new Date();
Date lastRequest = new Date();
boolean bot = false;//是否是机器h讉K
public Clickstream()
{
}
public void addRequest(HttpServletRequest request)
{
lastRequest = new Date();
if (hostname == null) {
hostname = request.getRemoteHost();
session = request.getSession();
}
// if this is the first request in the click stream
if (clickstream.size() == 0)
{
// setup initial referrer
if (request.getHeader("REFERER") != null)
{
initialReferrer = request.getHeader("REFERER");
}
else
{
initialReferrer = "";
}
// decide whether this is a bot
bot = BotChecker.isBot(request, this);
}
clickstream.add(request.getServerName() +
(request.getServerPort() != 80 ? ":" + request.getServerPort() : "") +
request.getRequestURI() +
(request.getQueryString() != null ? "?" + request.getQueryString() : ""));
// System.out.println(this.toString());
}
public String getHostname()
{
return hostname;
}
public boolean isBot()
{
return bot;
}
public void setBot(boolean value)
{
this.bot = value;
}
public HttpSession getSession()
{
return session;
}
public String getInitialReferrer()
{
return initialReferrer;
}
public Date getStart()
{
return start;
}
public Date getLastRequest()
{
return lastRequest;
}
public List getStream()
{
return clickstream;
}
public String toString()
{
StringBuffer output = new StringBuffer();
output.append("Clickstream for: " + hostname + "\n");
output.append("Session ID: " + (session != null ? session.getId() + "" : "") + "\n");
output.append("Initial Referrer: " + initialReferrer + "\n");
output.append("Stream started: " + start + "\n");
output.append("Last request: " + lastRequest + "\n");
long streamLength = lastRequest.getTime() - start.getTime();
output.append("Stream length:" +
(streamLength > 3600000 ?
" " + (streamLength / 3600000) + " hours" : "") +
(streamLength > 60000 ?
" " + ((streamLength / 60000) % 60) + " minutes" : "") +
(streamLength > 1000 ?
" " + ((streamLength / 1000) % 60) + " seconds" : "") +
"\n");
Iterator clickstreamIt = clickstream.iterator();
int count = 0;
while (clickstreamIt.hasNext())
{
count++;
output.append(count + ": " + clickstreamIt.next() + "\n");
}
return output.toString();
}
}
BotCheckercȝ来确定客L是否是一个机器h?br />
package com.java3z.examples;
import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class BotChecker
{
public static String[] botHosts = {"inktomi.com", "inktomisearch.com", "googlebot.com", "linuxtoday.com.au"};
public static boolean isBot(HttpServletRequest request, Clickstream stream)
{
String requestURI = request.getRequestURI();
// if it requested robots.txt, it's a bot
if (requestURI.indexOf("robots.txt") >= 0)
{
return true;
}
// it requested a RSS feed from our backend, it's a bot
if (requestURI.indexOf("/backend/") >= 0)
{
return true;
}
for (int i = 0; i < botHosts.length; i++)
{
if (request.getRemoteHost().indexOf(botHosts[i]) >= 0)
{
return true;
}
}
return false;
}
}
六、测试:请下载测试这个WEB应用的所有文件?/font>
]]>
q行Servlet开发所需要的基本环境是JSDK以及一个支持Servlet的Web服务器?
1.JSDK(Java Servlet Development Kit)
JSDK包含了编译Servlet应用E序所需要的Javacd以及相关的文档。对于利用Java 1.1q行开发的用户Q必d装JSDK。JSDK已经被集成进Java 1.2 Beta版中Q如果利用Java 1.2或以上版本进行开发,则不必安装JSDK?
JSDK可以在Javasoft公司的站点免费下载,其地址是: http://www.sun.com/software/jwebserver/redirect.html
2.支持Servlet的Web服务?/strong>
Servlet需要运行在支持Servlet的Web服务器上。目前支持Servlet的Web服务器SUN公司的JSWDK1.0.1。如果现有的Web服务器不支持ServletQ则可以利用一些第三方厂商的服务器增加?addQons)来Web服务器支持ServletQ这其中Live Software公司(http://www.livesoftware.com)提供了一U称为JRun的品,通过安装JRun的相应版本,可以使Microsoft IIS和Netscape Web Server支持Servlet?
开发Servlet的过E?/strong>
下面举一个简单的Servlet 例子来说明开发Servlet的过E?
1.~写Servlet代码
Java Servlet API是一个标准的Java扩展E序包,包含两个Package∶javax.servlet和javax.servlet.http。对于想开发基于客戯定义协议的开发者,应该使用javax.servlet包中的类与界面;对于仅利用HTTP协议与客Lq行交互的开发者,则只需要用javax.servlet.http包中的类与界面进行开发即可?
下面是一个servlet的程序代?RequestInfoExample.java)?
import java.io.*;
import java.servlet.*;
import javax.servlet.*;
public class RequestInfoExample extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("QhtmlQ?);
out.println("QbodyQ?);
out.println("QheadQ?);
out.println("QtitleQRequest Information ExampleQ?titleQ?);
out.println("Q?headQ?);
out.println("QbodyQ?);
out.println("Qh3QRequest Information ExampleQ?h3Q?);
out.println("Method: " + request.getMethod());
out.println("Request URI: " + request.getRequestURI());
out.println("Protocol: " + request.getProtocol());
out.println("PathInfo: " + request.getPathInfo());
out.println("Remote Address: " + request.getRemoteAddr());
out.println("Q?bodyQ?);
out.println("Q?htmlQ?);
}
public void doPost(HttpServletRequest request, HttpServletResponse res)
throws IOException, ServletException
{
doGet(request, response);
}
}
该servlet实现如下功能∶当用户通过览器访问该servletӞ该servlet向客L览器返回一个HTML面?
------------------------------------------------
Request Information Example
Method: GET
Request URI: /examples/servlet/RequestInfoExample
Protocol: HTTP/1.1
Path Info: null
Remote Address: 127.0.0.1
--------------------------------------------------
有关servletE序说明?
* ZHTTP协议的servlet必须引入javax.servlet和javax.servlet.http包;
* HelloServlet从类HttpServletzQHttpServlet是GenericServlet的一个派生类Q通过 GenericServlet实现了Servlet界面。HttpServlet为基于HTTP协议的servlet提供了基本的支持Q?
* HttpServletRequest对象包含了客Lh的信息,可以通过该参数取得客L的一些信?例如IP地址、浏览器cd{?以及HTTPhcd(例如GET、HEAD、POST、PUT{?QHttpServletResponse对象用于完成Servlet与客L的交互,通过调用HttpServletResponse.getOutputStream()客户取得向客Lq行输出的输出流Q向客户端发送HTML面?br />
* ~写了doGetҎQ对于HTML POST hQ调用Servlet 的doPost()Ҏ?
2.~译Servlet代码
利用JDK 1.2.2 对Servlet代码q行~译(假设Web服务器采用jswdk-1.0.1)Q其命o行ؓ:
c:\Q?javac Qd C:\jswdk-1.0.1\examples\WEB-INF\servlets HelloServlet.java
q行~译时必ȝ保HelloServlet.java 文g拯到目录C:\jswdk-1.0.1\examples\WEB- INF\servlets 下面?br />
3.试Servlet
现在可以对HelloServletq行试了,打开览器,键入Q?
http://localhost:8080/examples/servlet/RequestInfoExample
其中localhost是安装有jswdk-1.0.1的机器,8080是端口号?
下面是示例:
8 7 4 3 6 1 //是要排序的数|我们以一半的长度为间?
3 7 4 8 6 1 //W一ơ,取得3Q小于前面的8Q交换位|?br />
3 6 4 8 7 1 //W二ơ,取得6Q小于前面的7Q交换位|?br />
3 6 1 8 7 4 //W三ơ,取得1Q小于前面的4Q交换位|?br />
1 6 3 4 7 8 //W四ơ,再羃间隔,?Q取?于3Q交换位|,取得7Q大于前面的3Q不变;取得8大于6Q不变,取得4于8Q交换位|?br />
1 3 4 6 7 8 //W五ơ,再羃间隔,?Q取?Q大?Q不变;取得3于6Q交换位|;取得4Q小?Q交换位|;取得7Q大于前面的6Q不变;取得8 Q大?Q不?/code>
以下是代码:
void paixu( ) //用希排序法,
{
int N=13;// N为前后纪录位|的增量
for (int Z= N/2; Z; Z = Z/2)//每次~小增量
for (int i = Z; i < N; i++)//从增两大开始比?br />
{
int temp = apai[i]; //后一个备?br />
for (int j = i; j >= Z && temp < a[j - Z]; j -= Z) //与他在同一个子序列的数一个个的较
{
a[j] = a[j -Z]; //如果于,׃?br />
}//end for
a[j] = temp; //扑ֈ合适的插入?攑օ其中
}//end for
}//end
我们再来看最后一U关于数l的排序Ҏ,是快速排序法,它是目前最快的一U排序的Ҏ.它的基本思想?通过一排序将待排序的记录分割为独立的两部?其中一部分记录的数值均比另一部分记录的数值小,然后l箋分别对这两部分进行排?直到整个序列有序为止.
具体做法: d待排序列的某个记?我们可以取第一个数)作ؓ基准Q按照该数值大,整个序列分成两个序列——左侧的所有记录的数值都比基准小Q或者相{)Q右侧的都比基准大,基准则放在两个子序列之间Q显然这时基准放在了最后应该放|的位置。分别对左右子序列重复上面的q程Q直到最后所有的记录都放在相应的位置?br />
CZ如下:
7 8 4 3 6 1 //是要排序的数?br />
1 8 4 3 6 //W一ơ,取得7Q作为基准,1为right?7>1,交换位置
1 4 3 6 8 //W二? 8为left|7<8,攑ֈ最?
1 4 3 6 8 //W三ơ,left取得4Q小?Q放到前?
1 4 6 3 8 //W四?right?,于7,攑ֈ前面
1 4 6 3 8 //W五ơ,left=right=3,于7Q放到前?
1 4 6 3 7 8 //7攑օ合适位|?W一排序完?br />
//后面,在以1为基准排?br />
……
//直到成功
代码如下:
void paixu(int a[],int low,int high;)//用快速排序法
{
// low, high表示扫描的范?br />
int pivot;//存放中心索引及其值的局部变?br />
int scanup,scandown,mid;//用于扫描的烦?br />
if (high-low<=0) //如果数组中的元素于两个,则返?br />
return;
else
if(high-low==1) //如果有两个元?对其q行比较
{
if(apai[high]<apai[low]) //如果后一个比前一个小,
Swap(apai[low],apai[high]);//那么交换位置
return;
}//end if
mid=(low+high)/2;//取得中心索引
pivot=apai[mid];//中间烦引的?赋给pivot
Swap(apai[mid],apai[low]);//交换pivot及低端元素的?br />
Scanup=low+1;
Scandown=high;//初始化扫描烦引scanup和scandown
do{
//从低端子表向上扫?当scanupq入高端子表或遇到大于pivot的元素时l束.
while(scanup<=scandown && apai[scanup]<=pivot)
scanup++;
//从高端子表向下扫?当scandown遇到于或等于pivot的元素时l束
while(piovt<apai[scandown])
scandown--;
//如果两个索引q在各自的子表中,则表CZ个元素错?两个元素换?br />
if(scanup<scandown)
Swap(apai[scanup],apai[scandown]);
}while(scanup<scandown);
//pivot拯到scandown位置,分开两个子表
apai[low]=apai[scandown];
apai[scandown]=pivot;
//如果低端子表(low至scandown-1)?个或更多个元?则进行递归调用
if(low<scandown-1)
paixu(apai,low,scandown-1);
//如果高端子表(scandown+1至high) ?个或更多个元?则进行递归调用
if(scandown+1<high)
paixu(apai, scandown+1, high);
}
关于排序的问题已l够多了,到q里?如果大家有兴?可以看已看这斚w的书.
HttpServlet 是从GenericServlet l承而来Q因此它hGenericServlet cM的方法和对象Q是我们使用Servlet~程l常用到的包Q它支持HTTP 的post ?get {方法?br />
~程思\Q下面的例子Q运行结果是输出单地q回客户发送给服务器的h行和头部信息Q以及一些可讉K的HTTP 信息{?br />
SnoopServlet.java 的源代码如下Q?br />
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;
public class SnoopServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
out.println("Snoop Servlet");
out.println();
out.println("Servlet init parameters:");
Enumeration e = getInitParameterNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String value = getInitParameter(key);
out.println(" " + key + " = " + value);
}
out.println();
out.println("Context init parameters:");
ServletContext context = getServletContext();
Enumeration enum = context.getInitParameterNames();
while (enum.hasMoreElements()) {
String key = (String)enum.nextElement();
Object value = context.getInitParameter(key);
out.println(" " + key + " = " + value);
}
out.println();
out.println("Context attributes:");
enum = context.getAttributeNames();
while (enum.hasMoreElements()) {
String key = (String)enum.nextElement();
Object value = context.getAttribute(key);
out.println(" " + key + " = " + value);
}
out.println();
out.println("Request attributes:");
e = request.getAttributeNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
Object value = request.getAttribute(key);
out.println(" " + key + " = " + value);
}
out.println();
out.println("Servlet Name: " + getServletName());
out.println("Protocol: " + request.getProtocol());
out.println("Scheme: " + request.getScheme());
out.println("Server Name: " + request.getServerName());
out.println("Server Port: " + request.getServerPort());
out.println("Server Info: " + context.getServerInfo());
out.println("Remote Addr: " + request.getRemoteAddr());
out.println("Remote Host: " + request.getRemoteHost());
out.println("Character Encoding: " + request.getCharacterEncoding());
out.println("Content Length: " + request.getContentLength());
out.println("Content Type: "+ request.getContentType());
out.println("Locale: "+ request.getLocale());
out.println("Default Response Buffer: "+ response.getBufferSize());
out.println();
out.println("Parameter names in this request:");
e = request.getParameterNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String[] values = request.getParameterValues(key);
out.print(" " + key + " = ");
for(int i = 0; i < values.length; i++) {
out.print(values[i] + " ");
}
out.println();
}
out.println();
out.println("Headers in this request:");
e = request.getHeaderNames();
while (e.hasMoreElements()) {
String key = (String)e.nextElement();
String value = request.getHeader(key);
out.println(" " + key + ": " + value);
}
out.println();
out.println("Cookies in this request:");
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
out.println(" " + cookie.getName() + " = "+ cookie.getValue());
}
}
out.println();
out.println("Request Is Secure: " + request.isSecure());
out.println("Auth Type: " + request.getAuthType());
out.println("HTTP Method: " + request.getMethod());
out.println("Remote User: " + request.getRemoteUser());
out.println("Request URI: " + request.getRequestURI());
out.println("Context Path: " + request.getContextPath());
out.println("Servlet Path: " + request.getServletPath());
out.println("Path Info: " + request.getPathInfo());
out.println("Path Trans: " + request.getPathTranslated());
out.println("Query String: " + request.getQueryString());
out.println();
HttpSession session = request.getSession();
out.println("Requested Session Id: " +
request.getRequestedSessionId());
out.println("Current Session Id: " + session.getId());
out.println("Session Created Time: " + session.getCreationTime());
out.println("Session Last Accessed Time: " +session.getLastAccessedTime());
out.println("Session Max Inactive Interval Seconds: " + session.getMaxInactiveInterval());
out.println();
out.println("Session values: ");
Enumeration names = session.getAttributeNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
out.println(" " + name + " = " + session.getAttribute(name));
}
}
}
~程技巧说明:
E序输出Init Parameters(初始化参?、Attribute names in this request、Parameter names in this request、Headers in this request、Cookies in this request ?Session Information{信息?br />
ҎgetRequestURIq回的对象URI 是作为URL 的一部分Q是LURL 中用于指定机器的那部分;ҎgetPathInfo q回的字W串是客户向Servlet 传送的各种选项Q这些选项是跟在Servlet 的URL 之后的,ҎgetPathTranslated q回的字W串是Servlet 的自ql对路径名,SnoopServlet.class 文g位置是C:\jswdk-1.0.1\examples\WEB-INF\servlets\SnoopServlet.classQ则ҎgetPathTranslated q回的字W串值就是它?br />
在浏览器中输入如下的地址Q?br />
http://localhost:8080/examples/servlet/SnoopServlet
则会输出l果?br />
Cookie 是一块可以嵌入HTTP h和响应中的数据,它在服务器上产生Qƈ作ؓ响应头域的一部分q回用户。浏览器收到包含Cookie 的响应后Q会把Cookie 的内容用“关键??#8221; 对的形式写入C个客L专ؓ存放Cookie 的文本文件中。浏览器会把Cookie 及随后生的h发给相同的服务器Q服务器可以再次dCookie 中存Cookie 可以q行有效期设|,q期的Cookie 不会发送给服务器?br />
Servlet API 提供了一个Cookie c,装了对Cookie 的一些操作。Servlet 可以创徏一个新的CookieQ设|它的关键字、值及有效期等属性,然后把Cookie 讄在HttpServletResponse 对象中发回浏览器Q还可以从HttpServletRequest 对象中获取Cookie?br />
~程思\QCookie 在实际的Servlet ~程中是很广泛应用,下面是一个从Servlet 中获取Cookie 信息的例子?br />
ShowCookies.java 的源代码如下Q?br />
import javax.servlet.*;
import javax.servlet.http.*;
/**
* QpQThis is a simple servlet that displays all of the
* Cookies present in the request
*/
public class ShowCookies extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException
{
// Set the content type of the response
resp.setContentType("text/html;charset=gb2312");
// Get the PrintWriter to write the response
java.io.PrintWriter out = resp.getWriter();
// Get an array containing all of the cookies
Cookie cookies[] = req.getCookies();
// Write the page header
out.println("QhtmlQ?);
out.println("QheadQ?);
out.println("QtitleQServlet Cookie InformationQ?titleQ?);
out.println("Q?headQ?);
out.println("QbodyQ?);
if ((cookies == null) || (cookies.length == 0)) {
out.println("没有 cookies ");
}
else {
out.println("QcenterQ<h1Q响应消息中的Cookies 信息 Q?h1Q?);
// Display a table with all of the info
out.println("Qtable borderQ?);
out.println("QtrQ<thQNameQ?thQ<thQValueQ?thQ? + "QthQCommentQ?thQ<thQMax AgeQ?thQ</trQ?);
for (int i = 0; i Q?cookies.length; i++) {
Cookie c = cookies[i];
out.println("QtrQ<tdQ? + c.getName() + "Q?tdQ<tdQ? +
c.getValue() + "Q?tdQ<tdQ? + c.getComment() + "Q?tdQ<tdQ? + c.getMaxAge() + "Q?tdQ</trQ?);
}
out.println("Q?tableQ</centerQ?);
}
// Wrap up
out.println("Q?bodyQ?);
out.println("Q?htmlQ?);
out.flush();
}
/**
* QpQInitialize the servlet. This is called once when the
* servlet is loaded. It is guaranteed to complete before any
* requests are made to the servlet
* @param cfg Servlet configuration information
*/
public void init(ServletConfig cfg)
throws ServletException
{
super.init(cfg);
}
/**
* QpQDestroy the servlet. This is called once when the servlet
* is unloaded.
*/
public void destroy()
{
super.destroy();
}
}
注意QCookie q行服务器端与客L的双向交,所以它涉及到安全性问题?br />
javax.servlet.http.HttpSession 接口装了HTTP 会话的细节,该会话与一D|间内特定的Web 客户对Web 服务器的多个h相关。管理会话数据主要涉及到3个方面:会话交换、会话重定位和会话持久性,只有实现了java.io.Serializable 接口的数据对象才能够被交换、重定位和保持。这个接口主要是让对象具有序列化的能力,它可以将对象的状态信息写入Q意的输出中如:文g、网l连接等?br />
~程思\Q下面是实现一个简单在商场购物的例子,当用户选购商品(p果、收x和练习簿)攑օ购物袋中Q保存选购的商品信息?br />
ShowBuy.java 的源代码如下Q?br />
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class ShowBuy extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, java.io.IOException
{
String[] item={"p果","攉?,"l习?};
//获取会话对象
HttpSession session=req.getSession(true);
//获取选择的商品数?br />
Integer itemCount=(Interger) session.getValue("itemCount");
//如果没放入商品则数目?
if (itemCount==null){
itemCount=new Integer(0);
}
// Set the content type of the response
res.setContentType("text/html;charset=gb2312");
PrintWriter out=res.getWriter();
//取得POST上来的表单信?br />
String[] itemsSelected;
String itemName;
itemsSelected=req.getParameterValues("item");
//选中的商品放入会话对?br />
if(itemsSelected !=null){
for(int i=0;iQitemsSelected.length;i++){
itemName=itemsSelected[i];
itemCount=new Integer(itemCount.intValue()+1);
session.putValue("Item" + itemCount,itemName);
//商品名U定义ؓItemX
session.putValue("itemCount",itemCount);
//商品数量放入会话对?
}
}
// Write the page header
out.println("QhtmlQ?);
out.println("QheadQ?);
out.println("QtitleQ购物袋的内容</titleQ?);
out.println("Q?headQ?);
out.println("QbodyQ?);
out.println("QcenterQ<h1Q你攑֜购物袋中的商品是Q?Q?h1Q</centerQ?);
//购物袋的内容写入页?
for (int i = 1; i Q?itemCount.intValue(); i++) {
String item =(String) session.getValue("Item"+i);
//取出商品名称
out.println(items[Integer.parseInt(item)]);
out.println("QBRQ?);
}
// Wrap up
out.println("Q?bodyQ?);
out.println("Q?htmlQ?);
out.close();
}
}
客户端的ShowBuy.html 的源代码如下Q?br />
QHTMLQ?br />
QHEADQ?br />
QTITLEQ购物袋的实?Q?TITLEQ?br />
Q?HEADQ?br />
QBODYQ?br />
QCENTERQ<H1Q百货商场</H1Q</CENTERQ?br />
QHRQ?br />
QFORM ACTION='servlet/ShowBuy" METHOD="POST"Q?br />
选购商品
QpQ<INPUT TYPE="Checkbox" NAME="item" VALUE="0"Q?br />
W一U:p果Q?pQ?br />
QpQ<INPUT TYPE="Checkbox" NAME="item" VALUE="1"Q?br />
W二U:攉机</pQ?br />
QpQ<INPUT TYPE="Checkbox" NAME="item" VALUE="2"Q?br />
W三U:l习</pQ?br />
QHRQ?br />
QINPUT TYPE="Submit" NAME="bt_submit" VALUE="加入购物?Q?br />
Q?FORMQ?br />
Q?BODYQ?br />
Q?HTMLQ?/code>
~程技巧说明:
在Servlet 中进行会话管理时Q首先要获得会话对象。HttpServletRequest.getSession()对象q回与请求相关的当前HttpSession 对象Qƈ且当该对象不存在时就新创Z个对象;HttpServletRequest.getSession(true)实现相同的功能。如果参数是falseQ当不存在会话对象时Q将q回一个null 倹{?br />
//获取会话对象
HttpSession session=req.getSession(true);
//获取选择的商品数?br />
Integer itemCount=(Interger) session.getValue("itemCount");
具体操作Ӟ当用户选择商品后,单击“加入购物?按钮QServlet 输出用户选择的商品?/span>
]]>
删除了论坛中一些回复,或许应该改个名字叫:服务器之间的重定向!
最q在做一个单点登录的接口Q基本实现如下:
1. webApp-A
if (session.getAttribute("UserID") != null) {
response.sendRedirect(ssoURL);
}
2. webApp-B (在另外一台服务器?
昄d界面Q登录,然后q回我webApp-A的一URL
3. webApp-A Ҏ q回URL中的result参数判断d的结果,q设|session变量UserID
问题出在了在重定向到ssoURLQƈ从webAPP-Bq回后,weblogic的sessionid变了Q所有的session 变量都没有了Q刷Cơsessionid变一?同样的程序用tomcat一炚w题都没有Q不知道问题出在哪,该怎么解决
-------------------------------------------------------------------
webApp-A和webApp-B 分别跑在不同的服务器?br />
webApp-A 中会重定向到webApp-B的URL
webApp-B 中也会重定到webApp-A的URL
-----------------------------------------------------------------
试代码如下Q?br />
a.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>
a
</title>
</head>
<body bgcolor="#ffffff">
<h1>
JBuilder Generated JSP
</h1>
<%
out.println("SessionID:"+session.getId());
response.sendRedirect("http://localhost:8080/wtui/b.jsp");
%>
</body>
</html>
b.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>
b
</title>
</head>
<body bgcolor="#ffffff">
<h1>
JBuilder Generated JSP
</h1>
<%
out.println("SessionID:"+session.getId());
response.sendRedirect("http://localhost:7001/wtui/c.jsp");
%>
</body>
</html>
c.jsp
<%@ page contentType="text/html; charset=GBK" %>
<html>
<head>
<title>
c
</title>
</head>
<body bgcolor="#ffffff">
<h1>
JBuilder Generated JSP
</h1>
<% out.println("SessionID:"+session.getId());
%>
<A href="a.jsp"><br>q回</A>
</body>
</html>
把a.jsp,c.jsp 攑ֈ本机?001端口Qb.jsp 攑ֈ本机?080端口Q?br />
(我的7001端口是weblogic 8.1 sp2,8080端口是tomcat 5.0),然后 http://localhost:7001/wtui/a.jsp
最后可以看到c.jsp昄出来的session id, h一下页面,看看是不是每ơsession id 都在变?
---------------------------------------------------------------------------------------------------------------
今天下午ȝ是找C问题的原因了
只要把a.jsp中的
response.sendRedirect("http://localhost:8080/wtui/b.jsp");
改ؓ
response.sendRedirect("http://127.0.0.1:8080/wtui/b.jsp");
׃切正怺Q原来做模拟环境的时候没有找两台机器Q只是在同一机器开了两个端口?br />
不过我还是想知道Z么weblogic为出现这U问?br />
Ҏ一Q在servlet的init()Ҏ中缓存数?/p>
当应用服务器初始化servlet实例之后Qؓ客户端请求提供服务之前,它会调用q个servlet的init()Ҏ。在一个servlet的生命周期中Qinit()Ҏ只会被调用一ơ。通过在init()Ҏ中缓存一些静态的数据或完成一些只需要执行一ơ的、耗时的操作,可大大地提高系l性能?/p>
例如Q通过在init()Ҏ中徏立一个JDBCq接池是一个最佳例子,假设我们是用jdbc2.0的DataSource接口来取得数据库q接Q在通常的情况下Q我们需要通过JNDI来取得具体的数据源。我们可以想象在一个具体的应用中,如果每次SQLh都要执行一ơJNDI查询的话Q那pȝ性能会急剧下降。解x法是如下代码Q它通过~存DataSourceQ得下一ơSQL调用时仍然可以l利用它Q?/p>
public class ControllerServlet extends HttpServlet
{
private javax.sql.DataSource testDS = null;
public void init(ServletConfig config) throws ServletException
{
super.init(config);
Context ctx = null;
try
{
ctx = new InitialContext();
testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}
catch(NamingException ne)
{
ne.printStackTrace();
}
catch(Exception e)
}
public javax.sql.DataSource getTestDS()
{
return testDS;
}
...
...
}
Ҏ 2:止servlet和JSP 自动重蝲(auto-reloading)
Servlet/JSP提供了一个实用的技术,卌动重载技术,它ؓ开发h员提供了一个好的开发环境,当你改变servlet和JSP面后而不必重启应用服务器。然而,q种技术在产品q行阶段对系l的资源是一个极大的损耗,因ؓ它会lJSP引擎的类装蝲?classloader)带来极大的负担。因此关闭自动重载功能对pȝ性能的提升是一个极大的帮助?/p>
Ҏ 3: 不要滥用HttpSession
在很多应用中Q我们的E序需要保持客L的状态,以便面之间可以怺联系。但不幸的是׃HTTPh天生无状态性,从而无法保存客L的状态。因此一般的应用服务器都提供了session来保存客L状态。在JSP应用服务器中Q是通过HttpSession对像来实现session的功能的Q但在方便的同时Q它也给pȝ带来了不的负担。因为每当你获得或更新sessionӞpȝ者要对它q行Ҏ的序列化操作。你可以通过对HttpSession的以下几U处理方式来提升pȝ的性能Q?/p>
· 如果没有必要Q就应该关闭JSP面中对HttpSession的缺省设|: 如果你没有明指定的话,每个JSP面都会~省地创Z个HttpSession。如果你的JSP中不需要用session的话Q那可以通过如下的JSP面指示W来止它:
Q?@ page session="false"%Q?nbsp;
· 不要在HttpSession中存攑֤的数据对像:如果你在HttpSession中存攑֤的数据对像的话,每当对它q行dӞ应用服务器都对其进行序列化Q从而增加了pȝ的额外负担。你在HttpSession中存攄数据对像大Q那pȝ的性能׃降得快?/p>
· 当你不需要HttpSessionӞ快地释攑֮Q当你不再需要sessionӞ你可以通过调用HttpSession.invalidate()Ҏ来释攑֮?/p>
· 量session的超时时间设得短一点:在JSP应用服务器中Q有一个缺省的session的超时时间。当客户在这个时间之后没有进行Q何操作的话,pȝ会将相关的session自动从内存中释放。超时时间设得越大,pȝ的性能׃低Q因此最好的Ҏ是量使得它的g持在一个较低的水^。方?4: 页面输行压~?/p>
压羃是解x据冗余的一个好的方法,特别是在|络带宽不够发达的今天。有的浏览器支持gzip(GNU zip)q行来对HTML文gq行压羃Q这U方法可以戏剧性地减少HTML文g的下载时间。因此,如果你将servlet或JSP面生成的HTML面q行压羃的话Q那用户׃觉得面览速度会非常快。但不幸的是Q不是所有的览器都支持gzip压羃Q但你可以通过在你的程序中查客L览器是否支持它。下面就是关于这U方法实现的一个代码片D:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
OutputStream out = null
String encoding = request.getHeader("Accept-Encoding");
if (encoding != null && encoding.indexOf("gzip") != -1)
{
request.setHeader("Content-Encoding" , "gzip");
out = new GZIPOutputStream(request.getOutputStream());
}
else if (encoding != null && encoding.indexOf("compress") != -1)
{
request.setHeader("Content-Encoding" , "compress");
out = new ZIPOutputStream(request.getOutputStream());
}
else
{
out = request.getOutputStream();
}
...
...
}
Ҏ 5: 使用U程?/p>
应用服务器缺省地为每个不同的客户端请求创Z个线E进行处理,qؓ它们分派service()ҎQ当service()Ҏ调用完成后,与之相应的线E也随之撤消。由于创建和撤消U程会耗费一定的pȝ资源Q这U缺省模式降低了pȝ的性能。但所q的是我们可以通过创徏一个线E池来改变这U状c另外,我们q要个线E池讄一个最线E数和一个最大线E数。在应用服务器启动时Q它会创建数量等于最线E数的一个线E池Q当客户有请求时Q相应地从池从取Z个线E来q行处理Q当处理完成后,再将U程重新攑օ到池中。如果池中的U程不够地话Q系l会自动地增加池中线E的数量Q但总量不能过最大线E数。通过使用U程池,当客Lh急剧增加Ӟpȝ的负载就会呈现的qx的上升曲U,从而提高的pȝ的可伸羃性?/p>
Ҏ 6: 选择正确的页面包含机?/p>
在JSP中有两种Ҏ可以用来包含另一个页面:1、用include指示W?Q?@ includee file=”test.jsp” %Q??、用jsp指示W?Qjsp:includee page=”test.jsp” flush=”true”/Q?。在实际中我发现Q如果用第一U方法的话,可以使得pȝ性能更高?/p>
Ҏ 7:正确地确定javabean的生命周?/p>
JSP的一个强大的地方是对javabean的支持。通过在JSP面中用<jsp:useBeanQ标{,可以javabean直接插入C个JSP面中。它的用方法如下:
Qjsp:useBean id="name" scope="page|request|session|application" class=
"package.className" type="typeName"Q?/p>
Q?jsp:useBeanQ?
其中scope属性指Zq个bean的生命周期。缺省的生命周期为page。如果你没有正确地选择bean的生命周期的话,它将影响pȝ的性能?/p>
举例来说Q如果你只想在一ơ请求中使用某个beanQ但你却这个bean的生命周期设|成了sessionQ那当这ơ请求结束后Q这个bean仍然保留在内存中,除非session时或用户关闭浏览器。这样会耗费一定的内存Qƈ无谓的增加了JVM垃圾攉器的工作量。因此ؓbean讄正确的生命周期,q在bean的命结束后快地清理它们,会用系l性能有一个提高?/p>
其它一些有用的Ҏ
· 在字W串q接操作中尽量不使用“Q?#8221;操作W:在java~程中,我们常常使用“Q?#8221;操作W来几个字W串q接hQ但你或总来没有想到过它居然会对系l性能造成影响吧?׃字符串是帔RQ因此JVM会生一些时的对像。你使用?#8220;Q?#8221;多Q生成的临时对像p多,q样也会l系l性能带来一些媄响。解决的Ҏ是用StringBuffer对像来代?#8220;Q?#8221;操作W?/p>
· 避免使用System.out.println()ҎQ由于System.out.println()是一U同步调用,卛_调用它时Q磁盘I/O操作必须{待它的完成Q因此我们要量避免对它的调用。但我们在调试程序时它又是一个必不可的方便工具Qؓ了解册个矛盾,我徏议你最好用Log4j工具(http://Jakarta.apache.org )Q它既可以方便调试,而不会生System.out.println()q样的方法?/p>
· ServletOutputStream ?PrintWriter的权?使用PrintWriter可能会带来一些小的开销Q因为它所有的原始输出都{换ؓ字符来输出Q因此如果用它来作为页面输出的话,pȝ要负担一个{换过E。而用ServletOutputStream作ؓ面输出的话׃存在一个问题,但它是以二进制进行输出的。因此在实际应用中要权衡两者的利弊?/p>
ȝ
本文的目的是通过对servlet和JSP的一些调优技术来极大地提高你的应用程序的性能Qƈ因此提升整个J2EE应用的性能。通过q些调优技术,你可以发现其实ƈ不是某种技术^収ͼ比如J2EE?NET之争Q决定了你的应用E序的性能Q重要是你要对这U^台有一个较为深入的了解Q这样你才能从根本上对自q应用E序做一个优化!