<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>Apusic初学者园地</title>
    <description>J2EE咨询顾问——多年J2EE软件开发和系统架构经验，多年政府行业软件开发和维护经验，具备支撑大型政府项目能力。</description>
    <link>http://zhuyuanxiang.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>Apusic上用JavaMail发邮件</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/236775" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/236775</a>&nbsp;
          发表时间: 2008年09月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>0. JavaMail基本介绍<br />&nbsp;JavaMail是属于J2EE框架中的一部分，主要是为简化Mail部分开发工作。使用JavaMail发送邮件需要以下步骤：<br />&nbsp;1）初始化Session实例；<br />&nbsp;在初始化Session实例中有两种方式：使用JNDI初始化和在代码中自行完成初始化。<br />&nbsp;2）初始化Message实例，填充相关信息；<br />&nbsp;3）初始化Transport实例，连接到远程SMTP服务器，发送邮件。<br />&nbsp;在初始化Transport实例时也有两种情况：<br />&nbsp;★ 如果SMTP不需要认证，可以直接调用send()函数发送邮件，调用connect()函数将会在后台进行；<br />&nbsp;★ 如果SMTP需要认证，需要调用connect()函数，并提供认证需要的用户名／密码，才可以正确发送邮件。<br />&nbsp;<br />1. javax.mail.Session的初始化<br />1.1. 使用JNDI初始化(配置JavaMail的JNDI)<br />在Apusic的J2EE应用中找到apusic-application.xml文件，增加&lt;mail-session&gt;部分，示例如下：<br />&lt;apusic-application&gt;<br />&nbsp;&lt;module uri="web.war"&gt;<br />&nbsp;&nbsp;&lt;web /&gt;<br />&nbsp;&lt;/module&gt;<br />&nbsp;&lt;mail-session&gt;<br />&nbsp;&nbsp;&lt;jndi-name&gt;javamail/myMail&lt;/jndi-name&gt;<br />&nbsp;&nbsp;&lt;property name="mail.transport.protocol" value="smtp" /&gt;<br />&nbsp;&nbsp;&lt;property name="mail.smtp.host" value="smtp.163.com" /&gt;<br />&nbsp;&nbsp;&lt;property name="mail.smtp.user" value="user" /&gt;<br />&nbsp;&nbsp;&lt;property name="mail.smtp.password" value="password" /&gt;<br />&nbsp;&nbsp;&lt;property name="mail.smtp.auth" value="true" /&gt;<br />&nbsp;&nbsp;&lt;property name="mail.from" value="<a href="mailto:user@163.com">user@163.com</a>" /&gt;<br />&nbsp;&lt;/mail-session&gt;<br />&lt;/apusic-application&gt;</p>
<p>1.1.1. 通过JNDI找到JavaMail<br />1.1.1.1. 使用远程访问获得JavaMail<br />&nbsp;Hashtable env=new Hashtable();<br />&nbsp;env.put(Context.INITIAL_CONTEXT_FACTORY,"com.apusic.naming.jndi.CNContextFactory");<br />&nbsp;env.put(Context.PROVIDER_URL,"iiop://localhost:6888");<br />&nbsp;//插入相关验证信息<br />&nbsp;env.put(Context.SECURITY_CREDENTIALS,"admin" ) ;<br />&nbsp;env.put(Context.SECURITY_PRINCIPAL,"admin");<br />&nbsp;Context initCtx=new InitialContext(env);<br />&nbsp;System.out.println(initCtx.PROVIDER_URL);<br />&nbsp;//通过RMI 取得<br />&nbsp;Session myMailSession = (Session) initCtx.lookup("javamail/myMailNoAuth");<br />1.1.1.2. 使用Apusic默认方式获得JavaMail<br />&nbsp;Context initCtx = new InitialContext();<br />&nbsp;Session myMailSession = (Session) initCtx.lookup("javamail/myMailNoAuth");<br />&nbsp;System.out.println(myMailSession.getProperty("mail.smtp.host"));<br />&nbsp;<br />1.1.2. 通过资源注入配置JavaMail<br />&nbsp;@Resource(mappedName = "javamail/myMailAuth", type = javax.mail.Session.class, shareable = true, authenticationType = Resource.AuthenticationType.CONTAINER, description = "my email with auth")<br />&nbsp;private Session myAuthMailSession;<br />或者<br />&nbsp;@Resource(mappedName = "javamail/myMailAuth")<br />&nbsp;private Session myAuthMailSession;</p>
<p>1.2. 在代码中初始化<br />1.2.1. 无须认证的初始化<br />&nbsp;final Properties props = new Properties();<br />&nbsp;props.put("mail.transport.protocol", "smtp");<br />&nbsp;props.put("mail.smtp.auth", "false");<br />&nbsp;props.put("mail.smtp.host", "localhost");<br />&nbsp;Session myMailSession = Session.getInstance(props);<br />1.2.2. 需要认证的初始化<br />&nbsp;final Properties props = new Properties();<br />&nbsp;props.put("mail.transport.protocol", "smtp");<br />&nbsp;props.put("mail.smtp.auth", "true");<br />&nbsp;props.put("mail.smtp.host", "smtp.163.com");<br />&nbsp;Session myMailSession = Session.getInstance(props, new Authenticator() {<br />&nbsp;&nbsp;public PasswordAuthentication getPasswordAuthentication() {<br />&nbsp;&nbsp;&nbsp;return new PasswordAuthentication("user", "password");}&nbsp;});</p>
<p>1.4. 对Session调试的配置<br />●&nbsp;可以在mail-session中加入&lt;property name="mail.debug" value="true" /&gt;<br />●&nbsp;可以在Session初始化前加入props.put("mail.debug", "true");<br />●&nbsp;可以在Session初始化后,通过代码控制myMailSession.setDebug(true);</p>
<p>1.5. Properties的解释<br />◆&nbsp;mail.store.protocol：用于检索邮件的协议<br />◆&nbsp;mail.transport.protocol：用于传送邮件的协议<br />◆&nbsp;mail.host：默认的主机名，默认是本地计算机。<br />◆&nbsp;mail.user：默认的用户名。<br />◆&nbsp;mail.from：默认的返回地址。<br />◆&nbsp;mail.debug：是否输出DEBUG信息。默认为False。<br />◆&nbsp;mail.protocol.host：指定协议的主机名，没有指定就用mail.host。例如：mail.smtp.host=smtp.163.com<br />◆&nbsp;mail.protocol.user：指定协议的用户名，没有指定就用mail.user。例如：mail.smtp.user=user<br />◆&nbsp;mail.protocol.from：指定协议的返回地址，没有指定就用mail.from。例如：<a href="mailto:mail.smtp.from=user@163.com">mail.smtp.from=user@163.com</a><br />◆&nbsp;mail.smtp.auth：如果是True，就会登录SMTP服务器，获得授权才能发送邮件。默认为False。</p>
<p><br />2. 通过JavaMail发送邮件<br />2.1. 通过无须认证的SMTP发邮件<br />&nbsp;&nbsp;final Properties props = new Properties();<br />&nbsp;&nbsp;props.put("mail.transport.protocol", "smtp");<br />&nbsp;&nbsp;props.put("mail.smtp.auth", "false");<br />&nbsp;&nbsp;props.put("mail.smtp.host", "localhost");<br />&nbsp;&nbsp;try {<br />&nbsp;&nbsp;&nbsp;Session myMailSession = Session.getInstance(props);<br />&nbsp;&nbsp;&nbsp;myMailSession.setDebug(true); // 打开DEBUG模式<br />&nbsp;&nbsp;&nbsp;Message msg = new MimeMessage(myMailSession);<br />&nbsp;&nbsp;&nbsp;msg.setFrom(new InternetAddress("<a href="mailto:user@163.com">user@163.com</a>"));<br />&nbsp;&nbsp;&nbsp;msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("<a href="mailto:zhuyuanxiang@apusic.com">zhuyuanxiang@apusic.com</a>"));<br />&nbsp;&nbsp;&nbsp;msg.setContent("I have a email test!", "text/plain");<br />&nbsp;&nbsp;&nbsp;msg.setSentDate(new java.util.Date());<br />&nbsp;&nbsp;&nbsp;msg.setSubject("Test");<br />&nbsp;&nbsp;&nbsp;msg.setText("This is a test!\n");<br />&nbsp;&nbsp;&nbsp;System.out.println("1.Please wait for sending one...");</p>
<p>&nbsp;&nbsp;&nbsp;// 发送邮件<br />&nbsp;&nbsp;&nbsp;// javax.mail.Transport.send(msg); // 与下面四行的功能一样<br />&nbsp;&nbsp;&nbsp;javax.mail.Transport myTransport = myMailSession.getTransport("smtp");<br />&nbsp;&nbsp;&nbsp;myTransport.connect();<br />&nbsp;&nbsp;&nbsp;myTransport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO));<br />&nbsp;&nbsp;&nbsp;myTransport.close();<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;System.out.println("2.Your message had send!");<br />&nbsp;&nbsp;} catch (Exception error) {<br />&nbsp;&nbsp;&nbsp;System.out.println("*.I am sorry to tell you the fail for " + error);<br />&nbsp;&nbsp;}</p>
<p>注：测试可以使用Microsft IIS SMTP 服务，安装好启动服务后，还需要进入&ldquo;IIS管理器&rdquo;，增加一个&ldquo;远程域&rdquo;，对于&ldquo;远程域&rdquo;的&ldquo;出站安全性&rdquo;需要把用户名和密码加上（就是平时发邮件时登录用的用户名／密码），否则邮件发不出去。</p>
<p>2.2. 通过需要认证的SMTP发邮件<br />2.2.1. 默认方式初始化Session<br />&nbsp;&nbsp;final Properties props = new Properties();<br />&nbsp;&nbsp;props.put("mail.transport.protocol", "smtp");<br />&nbsp;&nbsp;props.put("mail.smtp.auth", "true");</p>
<p>&nbsp;&nbsp;try {<br />&nbsp;&nbsp;&nbsp;Session myMailSession = Session.getInstance(props);<br />&nbsp;&nbsp;&nbsp;myMailSession.setDebug(true); // 打开DEBUG模式<br />&nbsp;&nbsp;&nbsp;Message msg = new MimeMessage(myMailSession);<br />&nbsp;&nbsp;&nbsp;msg.setFrom(new InternetAddress("<a href="mailto:user@163.com">user@163.com</a>"));<br />&nbsp;&nbsp;&nbsp;msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("<a href="mailto:zhuyuanxiang@apusic.com">zhuyuanxiang@apusic.com</a>"));<br />&nbsp;&nbsp;&nbsp;msg.setContent("I have a email test!", "text/plain");<br />&nbsp;&nbsp;&nbsp;msg.setSentDate(new java.util.Date());<br />&nbsp;&nbsp;&nbsp;msg.setSubject("Test");<br />&nbsp;&nbsp;&nbsp;msg.setText("This is a test!\n");<br />&nbsp;&nbsp;&nbsp;System.out.println("1.Please wait for sending two...");</p>
<p>&nbsp;&nbsp;&nbsp;// 发送邮件<br />&nbsp;&nbsp;&nbsp;javax.mail.Transport myTransport = myMailSession.getTransport("smtp");<br />&nbsp;&nbsp;&nbsp;myTransport.connect("smtp.163.com", "user", "password");<br />&nbsp;&nbsp;&nbsp;myTransport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO));<br />&nbsp;&nbsp;&nbsp;myTransport.close();<br />&nbsp;&nbsp;&nbsp;// javax.mail.Transport.send(msg); // 这行不能使用。<br />&nbsp;&nbsp;&nbsp;System.out.println("2.Your message had send!");<br />&nbsp;&nbsp;} catch (Exception error) {<br />&nbsp;&nbsp;&nbsp;System.out.println("*.I am sorry to tell you the fail for " + error);<br />&nbsp;&nbsp;}<br />&nbsp;}</p>
<p>2.2.2. 嵌入认证类初始化Session<br />&nbsp;final Properties props = new Properties();<br />&nbsp;props.put("mail.transport.protocol", "smtp");<br />&nbsp;props.put("mail.smtp.auth", "true");<br />&nbsp;props.put("mail.smtp.host", "smtp.163.com");</p>
<p>&nbsp;try {<br />&nbsp;&nbsp;Session myMailSession = Session.getInstance(props, new Authenticator() {<br />&nbsp;&nbsp;&nbsp;public PasswordAuthentication getPasswordAuthentication() {<br />&nbsp;&nbsp;&nbsp;&nbsp;return new PasswordAuthentication("user", "password");<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;});<br />&nbsp;&nbsp;myMailSession.setDebug(true);&nbsp;// 打开DEBUG模式<br />&nbsp;&nbsp;InternetAddress address = new InternetAddress("<a href="mailto:user@163.com">user@163.com</a>");<br />&nbsp;&nbsp;String message = "I have a email test!";<br />&nbsp;&nbsp;Message msg = new MimeMessage(myMailSession);<br />&nbsp;&nbsp;msg.setFrom(address);<br />&nbsp;&nbsp;msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("<a href="mailto:zhuyuanxiang@apusic.com">zhuyuanxiang@apusic.com</a>"));<br />&nbsp;&nbsp;msg.setContent(message, "text/plain");<br />&nbsp;&nbsp;msg.setSentDate(new java.util.Date());<br />&nbsp;&nbsp;msg.setSubject("Test");<br />&nbsp;&nbsp;msg.setText("This is a test!\n");<br />&nbsp;&nbsp;out.println("1.Please wait for sending...");<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;// 发送邮件<br />&nbsp;&nbsp;javax.mail.Transport myTransport = myMailSession.getTransport("smtp");<br />&nbsp;&nbsp;myTransport.connect();<br />&nbsp;&nbsp;myTransport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO));<br />&nbsp;&nbsp;myTransport.close();<br />&nbsp;&nbsp;// javax.mail.Transport.send(msg);&nbsp;// 注释上四行，打开这行代码，功能一样<br />&nbsp;&nbsp;out.println("2.Your message had send!");<br />&nbsp;} catch (Exception error) {<br />&nbsp;&nbsp;out.println("*.I am sorry to tell you the fail for " + error);<br />&nbsp;}</p>
<p>注：资源注入的Session发送邮件时：<br />无须认证的SMTP，可以参考2.1.<br />需要认证的SMTP，可以参考2.2.1.</p>
<p>参考：<br /><a href="http://java.sun.com/products/javamail/javadocs/com/sun/mail/smtp/package-summary.html">http://java.sun.com/products/javamail/javadocs/com/sun/mail/smtp/package-summary.html</a></p>
<p>备注：本文耗时1周完成。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/236775#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 04 Sep 2008 12:12:41 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/236775</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/236775</guid>
      </item>
      <item>
        <title>在Tomcat上开发Web应用如何保证兼容性 </title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/227868" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/227868</a>&nbsp;
          发表时间: 2008年08月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>最近，协助伙伴将Tomcat上开发的应用向Apusic移植时发现了一个兼容性问题。<br />应用中代码为：HashMap params = (HashMap) request.getParameterMap();<br /><br />而getParameterMap()在JCP规范中的定义为：<br />public java.util.Map getParameterMap()<br />Returns a java.util.Map of the parameters of this request. Request parameters are extra information sent with the request. For HTTP servlets, parameters are contained in the query string or posted form data.<br />请求的参数将返回一个java.util.Map。请求参数是请求发送的特别信息。对于HTTP servlets来说，参数包含在查询字符串或者发出的表单数据中。<br /><br />Returns: an immutable java.util.Map containing parameter names as keys and parameter values as map values. The keys in the parameter map are of type String. The values in the parameter map are of type String array.<br />一个不可更改的java.util.Map包含参数名称（关键字）和参数值（映射值）。参数映射中的关键字是String类型。参数映射中的值是String数组类型。<br /><br />可见规范中定义的返回值只是Map类型，而没有强制为HashMap。<br />Apusic在实现的时候也是Map作为返回值，而Tomcat返回时（参考org.apache.catalina.connector.Request.java）就是一个扩展自HashMap的ParameterMap类，因此开发时如何作为Map来用也不会出现问题，但是如果强制转换成HashMap就可能会与其他应用服务器产品无法正确兼容。<br /><br />Tomcat是一款非常不错的开源Web服务器，许多公司在软件开发时都使用Tomcat作为Web容器，并且Tomcat也较好的对Servlet和JSP规范进行了支持，因此许多在Tomcat上开发的应用都可以向其他商业应用服务器上进行移植。<br /><br />但是，Tomcat因为未去通过规范测试，因此可能会存在没有完全参考规范实现的部分，因此在开发中建议开发人员去<a href="http://www.jcp.org/">www.jcp.org</a>上去下载一个规范来进行参考，开发过程中尽可能按照规范给定的参数和返回值来使用系统的核心功能，从而避免在移植中出现不必要的问题。<br /><br />附注：出现问题也不可怕，总有许多方式可以解决，就如上文出现的Map与HashMap的问题。其实网上有许多Map向HashMap转换的代码，可以增加个过渡参数将得到的Map进行一次转换就可以不修改其他业务代码了。 </p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/227868#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 14 Aug 2008 07:43:21 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/227868</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/227868</guid>
      </item>
      <item>
        <title>Apusic Operamasks的资源注入</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/221930" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/221930</a>&nbsp;
          发表时间: 2008年07月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>★ 什么是资源？<br />开发过程中与业务无关的服务、类的实例或者变量的值。比如：Apusic J2EE应用服务器管理的JDBC服务是资源，用户开发的EJB、WebService是资源、用户定义的配置文件也是资源。</p>
<p><br />★ 为什么要资源注入？<br />大多数企业级java应用程序都使用了诸如DataSources,EJBs或WebService的外在的资源和服务，在J2EE 1.4中，用户必须在部署描述符中明确声明所依赖的资源或者使用JNDI的lookup方法去获得资源的引用。</p>
<p>最初目的是为了减少应用与资源的依赖度，具体可以参考IoC（控制反转）和DI（依赖注入），但现在作者认为优点很多：<br />1. 减少应用与资源的依赖度，便于应用的后期组装。例如：将数据库连接池在后期组装时作为资源注入到系统中，这样使应用在开发过程中不会与资源绑定。<br />2. 简化应用的复杂度，使程序员开发中更多关注业务。例如：通过标注将资源在变量定义的时候注入进去，开发人员直接可以使用变量，而无须再通过代码获得。<br />3. 规范应用的开发过程，提升应用后期运行的稳定性。例如：通过注入的方式使用资源，而无须在开发期管理资源的生命周期以及创建与销毁，避免出现重复创建或者内存泄漏。</p>
<p>★ 哪些资源可以注入？<br />数据源、JMS目的地、环境变量、EJB、WebService、上下文资源、Managed Bean、Spring Bean、LocalString</p>
<p>★ 如何注入和使用资源？<br />&nbsp;// Apusic系统日志，采用的是JDK 1.4的日志系统<br />&nbsp;@Inject<br />&nbsp;private java.util.logging.Logger logger;<br />&nbsp;public void IndexBean() {<br />&nbsp;&nbsp;logger.info("初始化IndexBean!");<br />&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp; // JavaServer Faces的相关资源<br />&nbsp;// JSF的FacesContext<br />&nbsp;@Inject<br />&nbsp;private javax.faces.context.FacesContext fContext;<br />&nbsp;&nbsp;&nbsp; // 获取应用的HttpRequest<br />&nbsp;&nbsp;&nbsp; HttpServletRequest request=(HttpServletRequest)fContext.getCurrentInstance().getExternalContext().getRequest();<br />&nbsp;&nbsp;&nbsp; // 获取应用的HttpResponse<br />&nbsp;&nbsp;&nbsp; HttpServletResponse request=(HttpServletResponse)fContext.getCurrentInstance().getExternalContext().getResponse();<br />&nbsp;&nbsp;&nbsp; // 获取应用的HttpSession<br />&nbsp;&nbsp;&nbsp; HttpSession session=(HttpSession) fContext.getCurrentInstance().getExternalContext().getSession(true);<br />&nbsp;&nbsp;&nbsp; // JSF的服务器实例<br />&nbsp;@Inject<br />&nbsp;private javax.faces.application.Application app;<br />&nbsp;// JSF的导航句柄<br />&nbsp;@Inject<br />&nbsp;private javax.faces.application.NavigationHandler nHandler;<br />&nbsp;// JSF的EL表达式工厂实例<br />&nbsp;@Inject<br />&nbsp;private javax.el.ExpressionFactory expFactory;<br />&nbsp;// JSF的事件广播者实例<br />&nbsp;@Inject<br />&nbsp;private org.operamasks.faces.event.EventBroadcaster event;<br />&nbsp;// 相同生命周期的ManagedBean，参考CRUD例子<br />&nbsp;@Inject<br />&nbsp;private IndexBean indexBean;</p>
<p>&nbsp;// JNDI资源注入<br />&nbsp;// 数据库连接池资源注入<br />&nbsp;@Resource(mappedName = "jdbc/CRUD")<br />&nbsp;private javax.sql.DataSource CRUD;<br />&nbsp; &nbsp;Connection con = CRUD.getConnection();<br />&nbsp;// 消息工厂资源注入<br />&nbsp;@Resource(mappedName="jms/ConnectionFactory")<br />&nbsp;private javax.jms.ConnectionFactory connFactory;<br />&nbsp;// 消息主题资源注入<br />&nbsp;@Resource(mappedName="testTopic")<br />&nbsp;private javax.jms.Topic topic;<br />&nbsp;// 消息队列资源注入<br />&nbsp;@Resource(mappedName="testQueue")<br />&nbsp;private javax.jms.Queue queue;<br />&nbsp;// 事务服务资源注入，一个线程只提供一个事务服务，因此不需要提供名称直接可以注入<br />&nbsp;@Resource<br />&nbsp;private javax.transaction.UserTransaction tx;<br />&nbsp;<br />&nbsp;// EJB资源注入<br />&nbsp;@EJB(name="com.apusic.examples.crud.second.service.PersonService")<br />&nbsp;IPersonService personService;<br />&nbsp;<br />&nbsp;// 资源文件的注入，注意：只能注入前缀为LocalStrings的文件组<br />&nbsp;@LocalString<br />&nbsp;private Map&lt;String, String&gt; messages;<br />&nbsp;messages.get("WindowBean.email.required");<br />&nbsp;<br />&nbsp;&nbsp;&nbsp; // 配置文件注入上下文资源<br />&nbsp;&nbsp;&nbsp; 在faces-config.xml中在需要注入的bean中加入managed-property属性和值<br />&nbsp;&lt;managed-bean&gt;<br />&nbsp;&nbsp;&lt;managed-bean-name&gt;windowBean&lt;/managed-bean-name&gt;<br />&nbsp;&nbsp;&lt;managed-bean-class&gt;<br />&nbsp;&nbsp;&nbsp;com.apusic.examples.crud.second.bean.WindowBean<br />&nbsp;&nbsp;&lt;/managed-bean-class&gt;<br />&nbsp;&nbsp;&lt;managed-bean-scope&gt;session&lt;/managed-bean-scope&gt;<br />&nbsp;&nbsp;&lt;managed-property&gt;<br />&nbsp;&nbsp;&nbsp;&lt;property-name&gt;injectName&lt;/property-name&gt;<br />&nbsp;&nbsp;&nbsp;&lt;property-class&gt;java.lang.String&lt;/property-class&gt;<br />&nbsp;&nbsp;&nbsp;&lt;value&gt;Operamasks&lt;/value&gt;<br />&nbsp;&nbsp;&lt;/managed-property&gt;<br />&nbsp;&lt;/managed-bean&gt;<br />&nbsp;在WindowBean.java中直接定义<br />&nbsp;private String injectName;<br />&nbsp;public void setInjectName(String injectName) { // 通过这个函数提供资源注入<br />&nbsp;&nbsp;this.injectName = injectName;<br />&nbsp;}<br />★ 参考资料<br /><a href="http://www.matrix.org.cn/resource/article/2006-04-05/Dependency+Injection_44321.html">http://www.matrix.org.cn/resource/article/2006-04-05/Dependency+Injection_44321.html</a></p>
<p>★ 备注<br />本文现在只介绍了基础资源注入知识，随着作者本人对资源注入的理解，将会继续补充与完善。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/221930#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 30 Jul 2008 23:58:50 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/221930</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/221930</guid>
      </item>
      <item>
        <title>Spring ImageDB在Apusic上部署</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/216506" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/216506</a>&nbsp;
          发表时间: 2008年07月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><strong>目标：<br /></strong>Spring的ImageDB例子在Apusic V5.1上部署</p>
<p><strong>术语：</strong><br />Apusic：提供了完整的J2EE支持的商用服务器；<br />Spring：开源框架，是其他各种框架的粘合剂；<br />Oracle：著名的商业关系数据库系统；<br />MySQL：著名的开源关系数据库系统；<br />%APUSIC_HOME%：Apusic安装目录；<br />%JAVA_HOME%：JDK安装目录。</p>
<p><strong>准备：</strong><br />在<a href="http://java.sun.com/">http://java.sun.com</a>下载JDK V1.5以上的版本并安装，确认JAVA_HOME正确指向装好的JDK目录；<br />在<a href="http://www.apusic.com/">http://www.apusic.com</a>下载Apusic V5.1以上的版本并安装；<br />在<a href="http://www.springframework.org/download">http://www.springframework.org/download</a>上下载spring-framework-2.0.6-with-dependencies.zip（不过很遗憾，最近国内用户好像无法从sourceforge.net上下载东西，大家通过Google找找其他镜像网站吧）并解压缩到%APUSIC_HOME%/temp目录下；<br />在<a href="http://downloads.mysql.com/archives.php">http://downloads.mysql.com/archives.php</a>上下载MySQL Database V5.1并安装，下载MySQL Connector/J 3.1.14并解压缩到%APUSIC_HOME%/temp目录下。<br /><br /><strong>过程：<br /></strong>1. 执行%APUSIC_HOME%/domains/mydomain/bin/startapusic.cmd，访问主页：<a href="http://localhost:6888/">http://localhost:6888/</a>，确认Apusic已经成功安装，在窗口模式下按Ctrl+C停止服务器（记住因为是批处理还需要按Y确认）；<br />2. 安装MySQL数据库服务器，然后执行MySQL Query Browser，确认数据库正确安装、启动并可以连接使用；<br />3. 在%APUSIC_HOME%/temp/samples/imagedb/db目录下找到mysql-schema.txt文件，将这个文件中的脚本放到MySQL Query Browser中执行，创建新表imagedb；<br />4. 在%APUSIC_HOME%/temp/samples/imagedb/war/WEB-INF目录下找到jdbc.properties文件，打开并修改与JDBC相关的配置文件(注意配置正确的数据库名和用户名／)；<br />&nbsp;jdbc.driverClassName=com.mysql.jdbc.Driver<br />&nbsp;jdbc.url=jdbc:mysql://localhost:3306/mysql<br />&nbsp;jdbc.username=root<br />&nbsp;jdbc.password=password<br />&nbsp;imageDatabase.lobHandler=defaultLobHandler<br />5. 在%APUSIC_HOME%/temp/mysql-connector-java-3.1.14目录下找到mysql-connector-java-3.1.14-bin.jar文件，拷贝到%APUSIC_HOME%/domains/mydomain/lib目录下，为应用提供支持JDBC的访问数据库的JAR包；<br />6. 找到samples/imagedb目录，执行warfile.bat生成dist/imagedb.war文件，将imagedb.war文件拷贝到%APUSIC_HOME%/domains/mydomain/applications/目录下，重新启动Apusic，稍等一会待Apusic自动部署，部署成功；<br />7. 有了前面的准备工作，访问<a href="http://localhost:6888/imagedb/">http://localhost:6888/imagedb/</a>，一切成功。</p>
<p><strong>备注：<br /></strong>1. 由于Apusic的ClassLoader需要将Spring框架载入，所以第一次启动时有点慢，请稍等一下。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/216506#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 Jul 2008 15:30:31 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/216506</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/216506</guid>
      </item>
      <item>
        <title>Spring Countries在Apusic上部署 </title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/214943" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/214943</a>&nbsp;
          发表时间: 2008年07月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><strong>目标：</strong> <br />Spring的Countries例子在Apusic V5.1上部署</p>
<p><strong>术语：</strong> <br /><a href="http://www.apusic.com/" title="金蝶中间件" target="_blank">Apusic</a>：提供了完整的J2EE支持的商用服务器；<br />Spring：开源框架，是其他各种框架的粘合剂；<br />%APUSIC_HOME%：Apusic安装目录；<br />%JAVA_HOME%：JDK安装目录。</p>
<p><strong>准备：</strong> <br />在<a href="http://java.sun.com/">http://java.sun.com</a>下载JDK V1.5以上的版本并安装，确认JAVA_HOME正确指向装好的JDK目录；<br />在<a href="http://www.apusic.com/">http://www.apusic.com</a>下载Apusic V5.1以上的版本并安装；<br />在<a href="http://www.springframework.org/download">http://www.springframework.org/download</a>上下载spring-framework-2.0.6-with-dependencies.zip（不过很遗憾，最近国内用户好像无法从sourceforge.net上下载东西，大家通过Google找找其他镜像网站吧）。</p>
<p><strong>过程：</strong> <br />1. 执行%APUSIC_HOME%/domains/mydomain/bin/startapusic.cmd，访问主页：<a href="http://localhost:6888/">http://localhost:6888/</a>，确认Apusic已经成功安装，在窗口模式下按Ctrl+C停止服务器（记住因为是批处理还需要按Y确认）；<br />2. 解压缩spring的文件到%APUSIC_HOME%/temp目录下，然后找到samples/countries目录，执行warfile.bat生成dist/countries.war文件，将countries.war文件拷贝到%APUSIC_HOME%/domains/mydomain/applications/目录下，重新启动Apusic，稍等一会待Apusic自动部署，部署成功访问<a href="http://localhost:6888/countries/">http://localhost:6888/countries/</a>，一切成功。<br />3. &ldquo;没有什么路途是一帆风顺的&rdquo;。当点页面上Config时，系统报错:java.lang.NullPointerException，org.springframework.samples.countries.DefaultCountryService.getFilteredCountries(DefaultCountryService.java:59)读源代码，原来系统的的国家属性只支持EN、FR和DE，现在打开&ldquo;工具&rarr;Internet选项&rarr;语言&rdquo;，添加&ldquo;英语[en]&rdquo;，再访问现在好了。</p>
<p><br /><strong>备注：</strong> <br />1. 由于Apusic的ClassLoader需要将Spring框架载入，所以第一次启动时有点慢，请稍等一下。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/214943#comments" style="color:red;">已有 <strong>1</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 15 Jul 2008 13:45:26 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/214943</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/214943</guid>
      </item>
      <item>
        <title>Struts的例子在Apusic V5.1上的部署记录 </title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/213714" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/213714</a>&nbsp;
          发表时间: 2008年07月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><strong>目标：<br /></strong>将Struts提供的例子部署到Apusic V5.1上，并且可以正确运行。<br />因为Struts 1.x与Struts 2.x有较大区别，因此本文对两个版本的例子都进行了部署。</p>
<p><strong></strong></p>
<p><strong>术语：</strong><br />Struts：使用最为广泛的MVC框架。<br />Apusic：完全支持J2EE规范的商业应用服务器产品，最新版本V5.1可以提供对Java EE 5.0的完整实现。<br />%APUSIC_HOME%：Apusic安装目录</p>
<p><strong></strong></p>
<p><strong>准备：<br /></strong>在<a href="http://archive.apache.org/dist/struts/binaries/struts-2.0.9-all.zip">http://archive.apache.org/dist/struts/binaries/struts-2.0.9-all.zip</a>下载Struts V2.0.9的压缩包；<br />在<a href="http://archive.apache.org/dist/struts/binaries/struts-1.3.9-all.zip">http://archive.apache.org/dist/struts/binaries/struts-1.3.9-all.zip</a>下载Struts V1.3.9的压缩包；<br />在<a href="http://java.sun.com/javase/downloads/index_jdk5.jsp">http://java.sun.com/javase/downloads/index_jdk5.jsp</a>下载JDK V1.5以上的版本并安装，确认JAVA_HOME正确指向装好的JDK目录；<br />在<a href="http://www.apusic.com/dist/apusicAS/v5.1/Apusic-5.1-OS-Independent.zip">http://www.apusic.com/dist/apusicAS/v5.1/Apusic-5.1-OS-Independent.zip</a>下载Apusic V5.1并解压；</p>
<p><strong></strong></p>
<p><strong>Struts 2.x的部署过程：<br /></strong>1. 执行%APUSIC_HOME%/domains/mydomain/bin/startapusic.cmd，访问主页：<a href="http://localhost:6888/">http://localhost:6888/</a>，确认Apusic已经成功安装；<br />2. 打开Struts V2.0.9的例子包，如果下载的是完整的Struts则在APP目录下；<br />3. 将struts2-blank-2.0.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts2-blank-2.0.9/">http://localhost:6888/struts2-blank-2.0.9/</a>访问一下，已经OK了。（好棒好简单。。。）<br />4. 将struts2-mailreader-2.0.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<br /><a href="http://localhost:6888/struts2-mailreader-2.0.9/">http://localhost:6888/struts2-mailreader-2.0.9/</a>访问一下，已经OK了。（好棒好简单。。。）<br />5. 将struts2-showcase-2.0.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），不会那么没创意吧，又成功啦？自动部署完成，但是后台部署过程报错：<br />javax.servlet.ServletException: java.lang.IllegalStateException: Application was not properly initialized at startup, co<br />uld not find Factory: javax.faces.context.FacesContextFactory<br />这个错误是跟JSF有关的，原因现在搞不懂，不管他。先用<a href="http://localhost:6888/struts2-showcase-2.0.9/">http://localhost:6888/struts2-showcase-2.0.9/</a>访问一下，好像没啥问题，进入主页一看例子提供了不少使用Struts的方法很值得学习，一一点过都很正常，而且还看到了JavaServer Faces，看样子Struts也在追赶潮流啦，点进去&rarr;再点List available Employees （<a href="http://localhost:6888/struts2-showcase-2.0.9/jsf/employee/list.action">http://localhost:6888/struts2-showcase-2.0.9/jsf/employee/list.action</a>）出错啦，去Apusic的后台看看。又有新的错误信息：<br />Unable to initialize jsf interceptors probably due missing JSF implementation libraries，说我没有提供实现库。不可能呀，Apusic已经提供了Operamasks的JSF实现呀，不过Struts肯定不会用Operamasks的，那是不是自带的JSF实现呢？打开WAR包进入WEB-INF/lib发现里面还有MyFaces的实现库。估计是两种JSF实现冲突了。看样子要动点脑筋了！<br />整个简单的办法，把Apusic的所有与JSF相关的JAR包都删除掉，让Apusic V5.1变成一个纯的WEB容器。与JSF相关的有三个文件：<br />● jsf-api.jar：%APUSIC_HOME%/common<br />● operamasks-impl.jar：%APUSIC_HOME%/lib<br />● operamasks-third-party.jar：%APUSIC_HOME%/lib/ext<br />停止应用服务器，把他们都删除掉，再重新启动后访问struts2-showcase-2.0.9.war的JSF例子，这下就行了。<br />7. 将struts2-portlet-2.0.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署也报错：<br />Could not load class org.apache.struts2.portlet.interceptor.PortletPreferencesInterceptor.看样子还需要加入Portal服务器才行，在网上搜了一下没有部署介绍，而且也说需要先部署好PortalServer支持，难度不小。尝试下了Pluto但是部署了没起作用，后来下了2.1.2版本，结果那个例子更成问题，只好先放弃。等到熟悉了Portal再回头补课。</p>
<p><strong></strong></p>
<p><strong>Struts 1.x的部署过程：</strong><br />1. 执行%APUSIC_HOME%/domains/mydomain/bin/startapusic.cmd，访问主页：<a href="http://localhost:6888/">http://localhost:6888/</a>，确认Apusic已经成功安装；<br />2. 打开Struts V1.3.9的例子包，如果下载的是完整的Struts则在apps目录下；<br />3. 将struts-blank-1.3.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts-blank-1.3.9/">http://localhost:6888/struts-blank-1.3.9/</a>访问一下，已经OK了；<br />4. 将struts-cookbook-1.3.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts-cookbook-1.3.9/">http://localhost:6888/struts-cookbook-1.3.9/</a>访问一下，已经OK了，访问里面的内容也可以正确执行；<br />5. 将struts-el-example-1.3.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts-el-example-1.3.9/">http://localhost:6888/struts-el-example-1.3.9/</a>访问一下，已经OK了，访问里面的内容也可以正确执行；<br />6. 将struts-examples-1.3.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts-examples-1.3.9/">http://localhost:6888/struts-examples-1.3.9/</a>访问一下，已经OK了，访问里面的内容也可以正确执行（这个例子其实是上面三个例子的集成）；<br />7. 下面的两个例子都与myfaces有关，为了防止JSF实现冲突，先停止服务器，将Apusic的JSF实现删除（参考Struts 2.x中的6）；<br />8. 将struts-faces-example1-1.3.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts-faces-example1-1.3.9/">http://localhost:6888/struts-faces-example1-1.3.9/</a>访问一下，已经OK了，访问里面的内容也可以正确执行；<br />9. 将struts-faces-example2-1.3.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts-faces-example2-1.3.9/">http://localhost:6888/struts-faces-example2-1.3.9/</a>访问一下，已经OK了，访问里面的内容也可以正确执行；<br />10. 将struts-mailreader-1.3.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts-mailreader-1.3.9/">http://localhost:6888/struts-mailreader-1.3.9/</a>访问一下，已经OK了(注意：我下载的这个例子图片无法正常显示，打开应用发现根本没有把图片文件打入WAR包)，访问里面的内容也可以正确执行；<br />11. 将struts-scripting-mailreader-1.3.9.war拖入%APUSIC_HOME%/domains/mydomain/applications目录下（稍等一下），自动部署完成，用<a href="http://localhost:6888/struts-scripting-mailreader-1.3.9/">http://localhost:6888/struts-scripting-mailreader-1.3.9/</a>访问一下，已经OK了(注意：我下载的这个例子图片无法正常显示，打开应用发现根本没有把图片文件打入WAR包)，访问里面的内容也可以正确执行。</p>
<p><strong></strong></p>
<p><strong>备注：<br /></strong>1. 删除了Operamasks的实现包，如果别的应用仍然想用Operamasks，最好的办法就是直接把这三个包加入到应用的WEB-INF/lib下面就可以了。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/213714#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 10 Jul 2008 23:02:14 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/213714</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/213714</guid>
      </item>
      <item>
        <title>经典框架在Apusic V5.1下部署文章撰写说明 </title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/213713" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/213713</a>&nbsp;
          发表时间: 2008年07月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>为了帮助越来越多的Apusic爱好者和使用者更加顺利的使用Apusic应用服务器，作者准备将大量经典的、并且应用广泛的框架例子部署到Apusic V5.1的应用服务器上，现在计划中的有：<br />● Struts V2.0.9<br />● Spring<br />● Hibernate<br />● iBatis<br />● Pluto<br />● Liferay<br />如果大家有其他的需要，可以在后面跟帖说明，作者会根据需求情况调整优先级或者加入新的框架。或者有其他朋友有兴趣撰写或者已经写了相类似的文章，也欢迎一起来共享和转帖。 </p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/213713#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 10 Jul 2008 23:01:06 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/213713</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/213713</guid>
      </item>
      <item>
        <title>Tomcat V6 Examples移植到Apusic V5.1</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/212393" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/212393</a>&nbsp;
          发表时间: 2008年07月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><strong>目标：</strong>将Tomcat V6的的例子Examples移植到Apusic V5.1上</p>
<p>&nbsp;</p>
<p><strong></strong></p>
<p><strong>术语：<br /></strong>Tomcat：只提供了WEB容器的开源服务器；<br />Apusic：提供了完整的J2EE支持的商用服务器；<br />%TOMCAT_HOME%：Tomcat安装目录<br />%APUSIC_HOME%：Apusic安装目录</p>
<p><strong></strong></p>
<p><strong>准备：<br /></strong>在<a href="http://java.sun.com">http://java.sun.com</a>下载JDK V1.5以上的版本并安装，确认JAVA_HOME正确指向装好的JDK目录；<br />在<a href="http://tomcat.apache.org">http://tomcat.apache.org</a>下载Tomcat V6以上的版本并安装；<br />在<a href="http://www.apusic.com">http://www.apusic.com</a>下载Apusic V5.1以上的版本并安装；</p>
<p>&nbsp;</p>
<p><strong>过程：<br /></strong>1. 执行%TOMCAT_HOME%/bin/startup.bat，访问例子Examples：<a href="http://localhost:8080/jsp">http://localhost:8080/jsp</a>，确认Tomcat和Examples成功安装，在窗口模式下按Ctrl+C停止服务器；<br />2. 执行%APUSIC_HOME%/domains/mydomain/bin/startapusic.cmd，访问主页：<a href="http://localhost:6888/">http://localhost:6888/</a>，确认Apusic已经成功安装，在窗口模式下按Ctrl+C停止服务器（记住因为是批处理还需要按Y确认）；<br />3. 找到%TOMCAT_HOME%/webapps/examples目录，将examples目录拷贝到%APUSIC_HOME%/domains/mydomain/applications/下，重新启动Apusic，稍等一会待Apusic自动部署，应用报错：java.lang.NoClassDefFoundError: org/apache/catalina/CometProcessor，这个错误是因为应用中使用了Tomcat内核的API（非J2EE规范），虽然编写这样的应用违背J2EE规范（JBoss和Resin也这样做过），但是既然应用已经这样使用必须想办法支持。<br />4. 一种方法是找出应用代码中的部分进行修改，很遗憾我没有找到；另一种就是把那个需要引用的类所在的catalina.jar文件拷贝到%APUSIC_HOME%/domains/mydomain/lib目录下，先停止Apusic应用服务器，然后重新启动。<br />5. 稍等一下，Apusic自动部署了examples应用，现在访问例子：<a href="http://localhost:6888/examples/">http://localhost:6888/examples/</a><br />6. 哇，成功了。就这么简单就可以完成Tomcat应用到Apusic应用的移植。<br />总结：Apusic是个符合J2EE规范的应用服务器，在Tomcat上开发的应用都可以非常简单的移植到Apusic上。并且Apusic同样支持WAR包（WEB模块）的直接部署。</p>
<p><strong></strong></p>
<p><strong>备注：<br /></strong>0. 访问<a href="http://localhost:6888/examples/jsp/jsp2/el/basic-arithmetic.jsp">http://localhost:6888/examples/jsp/jsp2/el/basic-arithmetic.jsp</a>出错了，为什么？<br />&nbsp;因为J2EE规范中除0是必须抛出错误，而Tomcat则没有遵守规范操作，请开发者注意。<br />&nbsp;当然，完美主义者还是希望看到正常显示的页面，那么请把这个文件中的3/0替换成3/4就可以了。<br />1. 打开examples应用的lib目录，会发现里面还有两个jar文件：jstl.jar和standard.jar，这是支持Standard Library用的，其实Apusic已经自带无须他们，现在停止Apusic服务器，再删除这两个JAR包，然后重新启动Apusic服务器，应用果然可以正常运行；<br />2. 移植时把catalina.jar全部拷过来了，里面包含了Tomcat对WEB容器的部分实现，那么肯定会疑虑系统到底在调用谁的实现呢？为了确认我们可以将Apusic服务器停止，用WINRAR打开catalina.jar文件，把里面与Comet无关的class全部删除，再重新启动Apusic服务器，应用仍然可以正常运行，现在没有疑虑了；<br />3. 为什么每次都需要停止服务器才能操作lib里面的JAR文件呢，难道Apusic不支持热部署？<br />Apusic当然支持热部署，将Examples直接拷贝到applications目录下其实就是热部署，你甚至可以在Apusic启动完成后再执行拷贝也可以。但是应用一旦被加载进应用服务器后，所有的jar文件全部会被锁定，以便保证应用的完整性，所以修改lib下的jar文件必须将应用服务器重新启动。<br />4. 建议不要部署压缩文件，而是部署将应用展开后的目录，因为对于压缩文件应用服务器启动时还需要一个解压过程，降低启动速度消耗系统资源；<br />5. 如何在Apusic上给WEB模块配置上下文呢？<br />&nbsp;现在打开%APUSIC_HOME%/domains/mydomain/config/server.xml可以看到新部署的examples的说明：&nbsp; <br />&lt;application name="examples" base="applications/examples" start="auto"/&gt;，因为examples不是标准的J2EE应用，导致WEB模块中没有指定上下文，因此可以使用name来指定上下文，比如：<br />&lt;application name="apusic-examples" base="applications/examples" start="auto"/&gt;就把应用的上下文换成apusic-examples了，访问自然也变成了<a href="http://localhost:6888/apusic-examples">http://localhost:6888/apusic-examples</a>，简单吧！</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/212393#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 07 Jul 2008 17:14:36 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/212393</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/212393</guid>
      </item>
      <item>
        <title>HP-UX+JDK+Apusic+SQL-Server的调优记录</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/211737" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/211737</a>&nbsp;
          发表时间: 2008年07月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>最近的项目，面临情况如下：<br />1. 并发压力大。平时并发连接大约在3000左右，高峰期是8000人上线访问，预期未来会达到20,000人同时在线。<br />2. 受到网络攻击。系统是接在公网上致使网络爬虫和攻击工具都可能给系统带来未知压力，甚至突然增加的并发访问导致系统瘫痪。<br />3. 数据库压力大。有大量的数据库访问操作，并且SQL语句中含有COUNT(*)或者JOIN等消耗系统资源的代码。</p>
<p>为了满足应用需要，特别对以下环境进行了调优。系统基本配置如下：<br />HP-UX V11.11　2CPU 4G<br />HP JDK V1.5<br />Apusic V5.0<br />SQL Server 2005</p>
<p>系统硬件条件已经确定，系统资源调用变化最频繁的就是应用服务器，因此应用服务器所在的操作系统、Java虚拟机(Java Virtual Machine, JVM)和Apusic AS都需要调优。而应用服务器对数据库的数据库连接池大小也必定会影响数据库服务器的相关压力，因此最后再根据稳定后的应用服务器调整数据库服务器配置。</p>
<p>1. 先调整JVM。这个先根据JVM所在的应用服务器物理内存的大小和JDK所支持的大小决定，建议是将空闲内存的70%～80%分配给JVM使用。下面是Java启动时用的配置参数：<br />-server -Xms1024m -Xmx1024m -Xmn?m -XX:MaxPermSize=256m -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xincgc、</p>
<p>注：1. 不同JDK在不同OS下所能使用的内存大小是不同<br />&nbsp;2. Heap的大小和分配现在设置的是经验值，是否调整最终还需要分析应用来定，一般经验值已经满足需要。<br />&nbsp;3. GC的机制对系统稳定也比较重要，尽可能参考JDK提供的最新GC参数。<br />&nbsp;4. 使用server版的JVM一般都会对应用系统提升带来帮助。</p>
<p>2. 再调整Apusic应用服务器。因为并发压力大，也意味着系统对CPU和内存的资源消耗都会比较大，为保证应用服务器的稳定修改apusic.conf的配置如下（只保留了修改的部分）：<br />2.1. 线程池调整<br />&nbsp;为了平衡用户访问速度与并发支持的关系，必须调整Apusic的线程池。调整前依据以下原则：<br />&nbsp;● 每CPU50用户的原则（线程池的设置可参考《Apusic AS V5.1线程池配置和调优》）。<br />&nbsp;● HTTPHandler是MuxHandler的三倍。<br />&lt;SERVICE<br />&nbsp;&nbsp;&nbsp; CLASS="com.apusic.util.ThreadPoolService"<br />&nbsp;&nbsp;&nbsp; NAME="apusic:service=ThreadPool,name=MuxHandler"<br />&nbsp;&nbsp;&nbsp; &gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxThreads" VALUE="100"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxSpareThreads" VALUE="30"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MinSpareThreads" VALUE="30"/&gt;<br />&lt;/SERVICE&gt;</p>
<p>&lt;SERVICE<br />&nbsp;&nbsp;&nbsp; CLASS="com.apusic.util.ThreadPoolService"<br />&nbsp;&nbsp;&nbsp; NAME="apusic:service=ThreadPool,name=HTTPHandler"<br />&nbsp;&nbsp;&nbsp; &gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxThreads" VALUE="300"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxSpareThreads" VALUE="100"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MinSpareThreads" VALUE="100"/&gt;<br />&lt;/SERVICE&gt;</p>
<p>2.2. Mux（多路复用服务）调优。多路复用是将客户端的服务申请分发给相应的服务，如：HTTP服务、JMS服务等等。因此该服务对资源占用时间较短，不需要分配太多线程，只需要关注他的接收能力和申请排队，保证申请不会丢失。<br />&lt;SERVICE<br />&nbsp;&nbsp;&nbsp; CLASS="com.apusic.net.Muxer"<br />&nbsp;&nbsp;&nbsp; &gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="NumberSelectors" VALUE="2"/&gt;<br />&nbsp;&lt;!-- 系统CPU核数，多个CPU使用多个Selectors可以加快并发处理能力 --&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="Port" VALUE="80"/&gt; <br />&nbsp;&lt;!-- 默认的服务端口 --&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="Backlog" VALUE="50"/&gt; <br />&nbsp;&lt;!-- TCP/IP的队列大小，如果有大量客户端连接超时，而服务器又没有足够的CPU压力，可以调大这个值 --&gt;<br />&lt;/SERVICE&gt;</p>
<p>2.3. WEB服务调优。<br />&lt;SERVICE<br />&nbsp;&nbsp;&nbsp; CLASS="com.apusic.web.WebService"<br />&nbsp;&nbsp;&nbsp; &gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="NumberSelectors" VALUE="2"/&gt;<br />&nbsp;&lt;!-- 系统CPU核数，多个CPU使用多个Selectors可以加快并发处理能力 --&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxKeepAliveConnections" VALUE="300"/&gt;<br />&nbsp;&lt;!-- 最大保持KeepAlive的连接数，与HTTPHandler保持一致 --&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxKeepAliveRequests" VALUE="600"/&gt;<br />&nbsp;&lt;!-- 最大保持KeepAlive的请求数，设HTTPHandler&times;2，大约一个连接支持两次请求，如果服务器硬件条件允许可以再开大些 --&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="WaitingClientTimeout" VALUE="15"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxWaitingClients" VALUE="200"/&gt;<br />&nbsp;&lt;!-- 等待队列满了后，将客户端请求抛弃的等待时间。如果关注系统反应的及时性，就把这个值调小，还可以把请求队列MaxWaitingClients调小；如果关注系统服务的有效性则要调大。--&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="KeepAlive" VALUE="True"/&gt;<br />&nbsp;&lt;!-- 默认打开KeepAlive，了解这个参数配置需要参看HTTP 1.1协议 --&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="ServletReloadCheckInterval" VALUE="-1"/&gt;<br />&nbsp;&lt;!-- 设为-1，意思就是不检查，因为这个功能是为开发阶段提供热部署的 --&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="KeepAliveTimeout" VALUE="15"/&gt;<br />&nbsp;&lt;!-- 服务器关闭客户端连接前等待下一次请求的时间，如果系统压力较大可以将这个值设小，以便应对更多的请求。 --&gt;<br />&lt;/SERVICE&gt;</p>
<p>2.3. Session服务<br />基本上采用默认值就可以了，如果需要配置集群才需要调整Session里面某些配置选项，具体可以参考Apusic集群配置。</p>
<p>2.4. 数据库连接池服务<br />&lt;datasources&gt;<br />&nbsp; &lt;datasource name="test"<br />&nbsp;&nbsp;&nbsp;&nbsp; jndi-name="jdbc/test"<br />&nbsp;&nbsp;&nbsp;&nbsp; driver-class="net.sourceforge.jtds.jdbc.Driver"<br />&nbsp;&nbsp;&nbsp;&nbsp; url="Jdbc:jtds:sqlserver://192.168.0.1:1433/test"<br />&nbsp;&nbsp;&nbsp;&nbsp; min-spare-connections="50"<br />&nbsp;&nbsp;&nbsp;&nbsp; max-spare-connections="50"<br />&nbsp;&nbsp;&nbsp;&nbsp; max-connections="150"<br />&nbsp;&nbsp;&nbsp;&nbsp; initial-connections="50"<br />&nbsp; &gt;<br />&nbsp;&nbsp;&nbsp; &lt;property name="user" value="sa"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;property name="test-before-reused" value="false"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;property name="password" value="test"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;property name="stmt-cache-size" value="50"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;property name="pre-fetch-size" value="50"/&gt;<br />&nbsp; &lt;/datasource&gt;<br />&lt;/datasources&gt;<br />min-spare-connections、max-spare-connections：在池中保留的空闲数据库连接数；<br />initial-connections：初始化的空闲数据库连接数；<br />三个值相同，保证在初始化时就有足够的数据库连接使用。<br />数据库连接数&times;2＝HTTP线程池数目<br />注：max-connections在现实中被调小。因为数据库服务器无法处理更多响应，因此原则是先保证拥有数据库连接的线程能够有效响应。</p>
<p>3. 调整HP-UX操作系统。<br />3.1. 首先调整核心资源，使用ulimit -a查看核心参数，特别关注file和memory两部分的使用，有些时候操作系统限制了进程打开文件数和内存使用数，无法有效利用硬件资源也会限制应用服务器性能的发挥。</p>
<p>3.2. 因为应用系统受到攻击，致使出现大量的CLOSE_WAIT、FIN_WAIT_2这样状态的连接，消耗大量系统资源。因此使用ndd进行网络参数配置，先用：ndd /dev/tcp，然后输入?，可以得到所有网络参数情况。使用：ndd -get /dev/tcp 参数名称，可以获得原参数的值。使用：ndd -set /dev/tcp 参数名称 参数值，可以设置新参数的值。例如：获得初始值：ndd -get /dev/tcp tcp_time_wait_interval，设置新值：ndd -set /dev/tcp tcp_time_wait_interval 30000，30000是毫秒单位=30秒。不能设置为0，0似乎是无限长的意思。需要关注的参数如下：<br />#与TIME_WAIT相关的参数，当系统出现大量此状态的连接时可以调小这个值<br />tcp_time_wait_interval &nbsp;&nbsp;30000<br />tcp_tw_cleanup_interval &nbsp;60000<br />#与FIN_WAIT相关的参数<br />tcp_fin_wait_2_timeout&nbsp; &nbsp;1000<br />#与KeepAlive相关的参数，因为应用服务器不负责KeepAlive连接的管理，因此这里由操作系统负责<br />tcp_keepalive_interval &nbsp;&nbsp;120000<br />tcp_keepalive_detached_interval&nbsp;120000<br />tcp_keepalives_kill &nbsp;&nbsp;1<br />tcp_ip_abort_interval &nbsp;&nbsp;600000<br />#与TCP连接数相关的参数<br />tcp_conn_request_max &nbsp;&nbsp;4096</p>
<p>4. 调整SQL Server数据库的参数。这个是因为数据库压力较大，才关注到这个部分调优。<br />4.1. 内存调整。因为SQL Server内存管理默认无限大，结果把系统资源全部耗尽，因此将服务器内存按照70～80%原则分配给SQL Server使用。<br />4.2. 处理器设置。主要是选择提升SQL Server的优先级和使用Windows纤程，保证SQL Server在操作系统中的执行速度。<br />4.3. 连接设置。控制最大并发连接数，比数据库连接池所设的连接数稍大就可以了，防止过多连接导致系统切换线程带来的资源消耗。同时合理设置查询的超时时间，保证资源不会被某个访问占用。<br />4.4. 活动监视器。通过活动监视器查看系统中的活动进程，以及执行的SQL语句，并且在系统压力较大时观察是否有资源被锁。<br />&nbsp;不过这些其实都只是帮助系统更好的运行，实际上SQL Server资源消耗问题的解决仍然领先应用的调整，应用发现某些表关联有问题，重新调整后CPU压力立刻降低。</p>
<p>&nbsp;以上是整个调优的过程记录。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/211737#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 04 Jul 2008 17:39:50 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/211737</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/211737</guid>
      </item>
      <item>
        <title>Apusic AS V5.1线程池配置和调优 </title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/207811" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/207811</a>&nbsp;
          发表时间: 2008年06月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&ldquo;没有最优，只有平衡&rdquo;。因此在配置与调优之前，我总喜欢先介绍理论基础。<br /><a href="http://www.apusic.com/" title="金蝶中间件" target="_blank">Apusic</a> AS V5.1的线程池只是个池服务，池中没有具体的线程，池中管理的线程是与业务相关的服务启动后并加入的。线程池只负责管理池中线程的数量和生命周期，从而简化了Apusic应用服务器的池管理框架。验证线程池的方法有以下几种：<br />1. 在Windows下启动Apusic V5.1的mydomain域，里面不带任何自启动线程的应用，在命令行窗口下按Ctrl+Break结果见附一（各人机器可能有所不同），发现系统没有任何与线程池相关的线程启动。打开IE访问一个HTML页面，再Ctrl+Break结果见附二，发现多了两个线程：Running HTTPHandler-1（HTTP服务线程）和Idle MuxHandler-1（多路复用服务线程），Mux空闲是因为多路复用的分配工作已经完成，而HTTP忙是因为HTTP服务刚结束，KeepAlive仍然保持着。可见线程池启动时是空的，当有服务时才生成线程加入到池中，池主要负责线程的数量和生命周期。这样的设定可以避免受到攻击时无限制地创建线程而导致系统宕机；或者合理使用机器的性能，平衡分配不同线程池中的线程数量。</p>
<p>2. 在apusic.conf文件中自定义一个线程池Test，然后可以在自己的代码中使用Apusic AS提供的池管理技术，当然如果没有使用这个池系统也仍然可以正常运行，因为这只是个池服务，只是没有线程加入到池中而已。<br />&lt;SERVICE<br />&nbsp;&nbsp;&nbsp; CLASS="com.apusic.util.ThreadPoolService"<br />&nbsp;&nbsp;&nbsp; NAME="<a href="http://www.apusic.com/" title="金蝶中间件" target="_blank">Apusic</a>:service=ThreadPool,name=Test"<br />&nbsp;&nbsp;&nbsp; &gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxThreads" VALUE="150"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="Priority" VALUE="5"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="ServicePriority" VALUE="H"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="IdleTimeout" VALUE="300"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxSpareThreads" VALUE="30"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MinSpareThreads" VALUE="5"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;ATTRIBUTE NAME="MaxQueueSize" VALUE="500"/&gt;<br />&lt;/SERVICE&gt;</p>
<p>3. 只提供default池，其他池都注释掉，系统依然能够正常运行，也是因为池与服务之间不是紧耦合，没有的相关的池，所有的线程统一使用default池，如果有自己的池就通过自定义池处理。<br />注意：如果有了自定义池，池中线程数达到最大值后，系统不会使用defalut池来处理的，从而充分保证相应服务池的控制。<br />例如：定义了HTTPHandler池，当HTTPHandler线程达到最大值后，其他只能在Queue中排队，如果Queue也满了，则其他请求将会被拒绝。</p>
<p><a href="http://www.apusic.com/" title="金蝶中间件" target="_blank">Apusic</a> AS自己使用了五种池：<br />default：Apusic AS系统默认的线程池<br />MuxHandler：多路复用的线程池，主要是将请求向不同的服务，如：HTTP、JMS、ORB等服务上分配<br />HTTPHandler：HTTP服务的线程池<br />JMSHandler：JMS服务的线程池<br />ORBHandler：ORB服务的线程池<br />了解了线程池的基本概念，就可以知道在线程池配置中default池最为重要，其他池可以根据需要增加或者注释，所有线程池的配置参数都是相同的，具体的配置参数解释如下：<br />MaxThreads：线程池中能够运行的最大线程数，也就是提供服务的线程数，-1代表无限制<br />MinSpareThreads，MaxSpareThreads：线程池中最小／最大空闲的线程数，当线程数符合这个区间时无论空闲多久都不会被销毁<br />IdelTimeout：空闲线程超时的时间，超时后会如果运行的线程总数大于MaxSpareThreads则被销毁<br />Priority（1～10）：受Java线程优先级管理<br />ServicePriority：服务启动的优先级，五种（H &gt; A &gt; N &gt; B &gt; L）<br />MaxQueueSize：当所有线程都忙时，为无法获得线程的请求提供队列进行排队，Size代表队列长度，队列满时请求被抛弃</p>
<p><a href="http://www.apusic.com/" title="金蝶中间件" target="_blank">Apusic</a> AS的线程池优化：<br />● 一般的WEB应用部署在Apusic上时，不会用到JMS和ORB服务，因此可以将这两个池注释掉，减少资源消耗。<br />● 如果应用现阶段使用人数不多，但是伴随着发展应用人数会不断增长，可以将MinSpareThreads调整为符合现阶段情况的值，将MaxSpareThreads调整为符合将来的值，这样系统无须再变动就可以有效支持很长一段时间；<br />● 如果应用一段时间内访问量变化不大，但是系统偶尔会遇到高峰访问，那么可以设置MinSpareThreads=MaxSpareThreads；<br />● MaxThreads的值依据CPU数量来定，参考值50&times;CPU核数，具体值还需要根据应用执行过程中对CPU的压力决定。<br />● 关于Apusic AS V5.1服务的配置，下篇文章会单独介绍。</p>
<p><br />附一、<br />Full thread dump Java HotSpot(TM) Client VM (1.5.0_14-b03 mixed mode, sharing):</p>
<p>"AutoDeployer" prio=6 tid=0x030f2970 nid=0x9e0 in Object.wait() [0x03cef000..0x03cefc6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x23460458&gt; (a com.apusic.deploy.runtime.AutoDeployer)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.deploy.runtime.AutoDeployer.run(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x23460458&gt; (a com.apusic.deploy.runtime.AutoDeployer)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Thread.run(Thread.java:595)</p>
<p>"Thread-4" prio=6 tid=0x031ca7f0 nid=0x21c in Object.wait() [0x0349f000..0x0349fd6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x2321c188&gt; (a com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Object.java:474)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive.run(Util.java:736)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x2321c188&gt; (a com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive)</p>
<p>"HTTPSessionSwapper" prio=6 tid=0x031d8168 nid=0xb98 in Object.wait() [0x0345f000..0x0345fa6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x2318ba58&gt; (a java.lang.Object)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.session.SessionManager$HouseKeeper.run(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x2318ba58&gt; (a java.lang.Object)</p>
<p>"HttpLogger" prio=2 tid=0x031be630 nid=0xfe8 in Object.wait() [0x0341f000..0x0341f9ec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x2317d2b8&gt; (a com.apusic.web.http.HttpLogger)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Object.java:474)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.HttpLogger.getNextRecord(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x2317d2b8&gt; (a com.apusic.web.http.HttpLogger)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.HttpLogger.run(Unknown Source)</p>
<p>"MuxListener" prio=6 tid=0x031a8be8 nid=0x7dc runnable [0x033df000..0x033dfaec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.PlainSocketImpl.socketAccept(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x23177890&gt; (a java.net.SocksSocketImpl)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.ServerSocket.implAccept(ServerSocket.java:450)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.ServerSocket.accept(ServerSocket.java:421)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.net.BlockingListenerThread.run(Unknown Source)</p>
<p>"Timer-0" prio=6 tid=0x031c3b08 nid=0xc98 in Object.wait() [0x0339f000..0x0339fb6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x23133120&gt; (a java.util.TaskQueue)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.util.TimerThread.mainLoop(Timer.java:509)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x23133120&gt; (a java.util.TaskQueue)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.util.TimerThread.run(Timer.java:462)</p>
<p>"LogManager" prio=2 tid=0x02e2c680 nid=0xb20 waiting on condition [0x0335f000..0x0335fbec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at sun.misc.Unsafe.park(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.util.concurrent.locks.LockSupport.park(LockSupport.java:118)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:<br />841)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.util.concurrent.LinkedBlockingQueue.take(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.logging.manager.ServerLogManager$PushThread.dequeue(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.logging.manager.ServerLogManager$PushThread.run(Unknown Source)</p>
<p>"Low Memory Detector" daemon prio=6 tid=0x00a83bf0 nid=0xa6c runnable [0x00000000..0x00000000]</p>
<p>"CompilerThread0" daemon prio=10 tid=0x00a537b8 nid=0xdc4 waiting on condition [0x00000000..0x02c2f6cc]</p>
<p>"Signal Dispatcher" daemon prio=10 tid=0x00a95a58 nid=0xeb0 waiting on condition [0x00000000..0x00000000]</p>
<p>"Finalizer" daemon prio=8 tid=0x00a50870 nid=0xbd0 in Object.wait() [0x02baf000..0x02bafa6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x230d25c8&gt; (a java.lang.ref.ReferenceQueue$Lock)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:120)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x230d25c8&gt; (a java.lang.ref.ReferenceQueue$Lock)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:136)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)</p>
<p>"Reference Handler" daemon prio=10 tid=0x00a4f3e8 nid=0xf94 in Object.wait() [0x02b6f000..0x02b6faec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x230d2650&gt; (a java.lang.ref.Reference$Lock)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Object.java:474)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x230d2650&gt; (a java.lang.ref.Reference$Lock)</p>
<p>"main" prio=6 tid=0x00038c00 nid=0x718 in Object.wait() [0x0007f000..0x0007fc3c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x230e0ed8&gt; (a com.apusic.server.J2EEServer)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Object.java:474)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.server.J2EEServer.startup(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x230e0ed8&gt; (a com.apusic.server.J2EEServer)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.server.Main.main(Unknown Source)</p>
<p>"VM Thread" prio=10 tid=0x00a80190 nid=0x490 runnable</p>
<p>"VM Periodic Task Thread" prio=10 tid=0x00a8e780 nid=0xcec waiting on condition</p>
<p>附二、<br />Full thread dump Java HotSpot(TM) Client VM (1.5.0_14-b03 mixed mode, sharing):</p>
<p>"Running HTTPHandler-1" prio=6 tid=0x02febe58 nid=0xbd8 runnable [0x03d6f000..0x03d6fb6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.SocketInputStream.socketRead0(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.SocketInputStream.read(SocketInputStream.java:129)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.io.BufferedInputStream.read(BufferedInputStream.java:313)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x234dd378&gt; (a java.io.BufferedInputStream)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.tcp.TCP_BIOProtocol.readLine(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.tcp.TCP_BIOProtocol.readRequestLine(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.tcp.TCP_BIOProtocol.read(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.tcp.TCP_BIOConnection.getNextRequest(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.ConnectionHandler.processConnection(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.ConnectionHandler.run(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.util.ThreadPoolImpl$WorkerThread.run(Unknown Source)</p>
<p>"Idle MuxHandler-1" prio=6 tid=0x02cc0d90 nid=0x54c in Object.wait() [0x03d2f000..0x03d2fbec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x23147df0&gt; (a java.lang.Object)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.util.ThreadPoolImpl.getWork(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x23147df0&gt; (a java.lang.Object)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.util.ThreadPoolImpl$WorkerThread.run(Unknown Source)</p>
<p>"AutoDeployer" prio=6 tid=0x03146980 nid=0x7bc in Object.wait() [0x03cef000..0x03cefc6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x2344f8c0&gt; (a com.apusic.deploy.runtime.AutoDeployer)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.deploy.runtime.AutoDeployer.run(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x2344f8c0&gt; (a com.apusic.deploy.runtime.AutoDeployer)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Thread.run(Thread.java:595)</p>
<p>"Thread-4" prio=6 tid=0x031e3868 nid=0xdc8 in Object.wait() [0x0349f000..0x0349fd6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x2321c188&gt; (a com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Object.java:474)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive.run(Util.java:736)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x2321c188&gt; (a com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive)</p>
<p>"HTTPSessionSwapper" prio=6 tid=0x031c1948 nid=0x9f4 in Object.wait() [0x0345f000..0x0345fa6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x2318ba58&gt; (a java.lang.Object)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.session.SessionManager$HouseKeeper.run(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x2318ba58&gt; (a java.lang.Object)</p>
<p>"HttpLogger" prio=2 tid=0x031b8830 nid=0xb2c in Object.wait() [0x0341f000..0x0341f9ec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x2317d2b8&gt; (a com.apusic.web.http.HttpLogger)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Object.java:474)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.HttpLogger.getNextRecord(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x2317d2b8&gt; (a com.apusic.web.http.HttpLogger)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.web.http.HttpLogger.run(Unknown Source)</p>
<p>"MuxListener" prio=6 tid=0x02e654a8 nid=0xa28 runnable [0x033df000..0x033dfaec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.PlainSocketImpl.socketAccept(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x23177890&gt; (a java.net.SocksSocketImpl)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.ServerSocket.implAccept(ServerSocket.java:450)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.ServerSocket.accept(ServerSocket.java:421)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.net.BlockingListenerThread.run(Unknown Source)</p>
<p>"Timer-0" prio=6 tid=0x02e65c08 nid=0xdf0 in Object.wait() [0x0339f000..0x0339fb6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x23133120&gt; (a java.util.TaskQueue)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.util.TimerThread.mainLoop(Timer.java:509)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x23133120&gt; (a java.util.TaskQueue)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.util.TimerThread.run(Timer.java:462)</p>
<p>"LogManager" prio=2 tid=0x02e2d488 nid=0xbfc waiting on condition [0x0335f000..0x0335fbec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at sun.misc.Unsafe.park(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.util.concurrent.locks.LockSupport.park(LockSupport.java:118)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1<br />841)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.util.concurrent.LinkedBlockingQueue.take(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.logging.manager.ServerLogManager$PushThread.dequeue(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.logging.manager.ServerLogManager$PushThread.run(Unknown Source)</p>
<p>"Low Memory Detector" daemon prio=6 tid=0x00a83c78 nid=0xc5c runnable [0x00000000..0x00000000]</p>
<p>"CompilerThread0" daemon prio=10 tid=0x00a53910 nid=0x780 waiting on condition [0x00000000..0x02c2f6cc]</p>
<p>"Signal Dispatcher" daemon prio=10 tid=0x00a95ae8 nid=0xc8c waiting on condition [0x00000000..0x00000000]</p>
<p>"Finalizer" daemon prio=8 tid=0x00a50870 nid=0xd10 in Object.wait() [0x02baf000..0x02bafa6c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x230d25c8&gt; (a java.lang.ref.ReferenceQueue$Lock)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:120)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x230d25c8&gt; (a java.lang.ref.ReferenceQueue$Lock)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:136)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)</p>
<p>"Reference Handler" daemon prio=10 tid=0x00a4f3e8 nid=0x1d0 in Object.wait() [0x02b6f000..0x02b6faec]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x230d2650&gt; (a java.lang.ref.Reference$Lock)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Object.java:474)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x230d2650&gt; (a java.lang.ref.Reference$Lock)</p>
<p>"main" prio=6 tid=0x00038c00 nid=0x7fc in Object.wait() [0x0007f000..0x0007fc3c]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Native Method)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - waiting on &lt;0x230e0ed8&gt; (a com.apusic.server.J2EEServer)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.Object.wait(Object.java:474)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.server.J2EEServer.startup(Unknown Source)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - locked &lt;0x230e0ed8&gt; (a com.apusic.server.J2EEServer)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at com.apusic.server.Main.main(Unknown Source)</p>
<p>"VM Thread" prio=10 tid=0x00a80190 nid=0xab4 runnable</p>
<p>"VM Periodic Task Thread" prio=10 tid=0x00a8e808 nid=0x684 waiting on condition</p>
<p>参考：<br /><a href="http://infocenter.apusic.com/help/index.jsp?topic=/com.apusic.studio.doc.server/output/eclipse/threadpool.html">http://infocenter.apusic.com/help/index.jsp?topic=/com.apusic.studio.doc.server/output/eclipse/threadpool.html</a></p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/207811#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 25 Jun 2008 12:32:10 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/207811</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/207811</guid>
      </item>
      <item>
        <title>HP-UX中CLOSE_WAIT问题解决 </title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/206041" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/206041</a>&nbsp;
          发表时间: 2008年06月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>作者一直被某个项目的HP-UX折磨，系统运行一段时间后就会出现大量的CLOSE_WAIT连接，然后Apusic应用服务器就一直处于非常繁忙的状态，但是Dump JVM发现Apusic的许多线程处在空闲状态，此时将Apusic重新启动将连接全部释放系统就恢复正常了。<br />分析认为因为系统在公网上受到攻击有关，攻击会建立大量的空闲连接，然后使连接处于CLOSE_WAIT状态，从而系统需要消耗大量的资源去维护这些连接直到断开，从而影响系统运行的效果。<br />为此，作者调整了相关的网络参数，效果比较明显，CPU压力大幅下降。<br />ndd -set /dev/tcp tcp_keepalive_interval 120000<br /><br />但是，对于生产系统许多时候是不希望宕机的，有没有直接断开CLOSE_WAIT连接呢？可以，先用<br />ndd -get /dev/tcp tcp_status |grep CLOSE_WAIT<br />把已经CLOSE_WAIT的连接找出来，然后使用<br />ndd -set /dev/tcp tcp_discon 0x&lt;TCP地址&gt;<br />例如：输入 ndd -get /dev/tcp tcp_status |grep 133<br />结果<br />000000005843e168 010.010.010.133&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 48a68cfa 48a68cf8 00008000 00008072 b64b7c33 b64b7c33 00008000 00500 01460 [17,c539] TCP_ESTABLISHED <br />再输入 ndd -set /dev/tcp tcp_discon 0x000000005843e168 <br />连接就会被主动断开了。<br />如果有人可以写个脚本定期执行，至少能够解决临时性问题，如果要真正解决可能还需要想其他办法，欢迎大家一起来讨论。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/206041#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 20 Jun 2008 07:58:32 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/206041</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/206041</guid>
      </item>
      <item>
        <title>上海药皂</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/204312" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/204312</a>&nbsp;
          发表时间: 2008年06月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>小的时候用过上海药皂，并没在意那个味道。长大了知道民办上香皂种类很多，还有洗手液，洗完喷喷香，比上海药皂高级多了，于是不再喜欢那个便宜货，对药皂的味道也讨厌起来。</p>
<p>工作了多年后，今天在重庆出差，无意间在超市又看到了上海药皂，不知为何突然觉得很亲切，价格还是那么便宜，样子也还是那么难看，并且还保持着传统的味道。但是这次我却不喜欢它周围那些漂亮的瓶瓶罐罐，花钱买它也不在乎别人看我是不是落伍。回到酒店洗完澡，发觉身上散出淡淡的味道很舒服，胜过以往的那些浓郁的味道。</p>
<p>可能，生活就是这样，原来怀念的仍是那种简单。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/204312#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 16 Jun 2008 20:57:40 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/204312</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/204312</guid>
      </item>
      <item>
        <title>Apusic AS的Web应用中调用commons-logging的流程</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/203278" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/203278</a>&nbsp;
          发表时间: 2008年06月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>上文描述了如何在Apusic AS的Web应用中调用Log4J，有些朋友会觉得Log4J使用前还需要初始化比较麻烦，还有些朋友会说&ldquo;怎么你这个Log4J使用起来那么复杂，我们的项目都没有那么过程呀？&rdquo;，那是因为许多Web应用中是用Java commons-logging(JCL)+Log4J的，如果采用JCL+Log4J就不需要初始化了。</p>
<p>那么为什么有了Log4J又有JCL呢？是因为SUN的JDK 1.4中自带有日志框架，Log4J是Apache提供的日志框架，为了扩展应用的兼容性，保证应用可以无缝切换到不同的日志框架，因此JCL提供的是日志系统的接口，通过给工厂接口提供不同的实现类，从而保证与不同日志框架的兼容。同时，为了保证系统的有效性，还提供了一个非常简单的日志框架实现，以便没有外接其他日志框架时可以使用自带的。</p>
<p>那么为什么JCL+Log4J就不需要初始化了呢？这要从JCL的执行流程说起。当应用执行类似以下代码时：</p>
<p>import org.apache.commons.logging.Log;<br />import org.apache.commons.logging.LogFactory;</p>
<p>public class LoggingDemo {<br />&nbsp;&nbsp;&nbsp; private static Log log = LogFactory.getLog(LoggingDemo.class);<br />&nbsp;&nbsp;&nbsp; // ...<br />}<br />LogFactory.getLog()函数会启动一个搜索过程，找出底层日志记录功能的实现，具体的发现过程在下面列出：</p>
<p>　　⑴ Commons的Logging首先在CLASSPATH中寻找一个commons-logging.properties文件。这个属性文件至少定义org.apache.commons.logging.Log属性，它的值应该是实现Log接口的完整限定名称。 </p>
<p>　　⑵ 如果上面的步骤失败，Commons的Logging接着检查系统属性org.apache.commons.logging.Log，以便找到实现Log接口的完整限定名称。属性可以通过服务器启动时参数配置，或者在代码中使用System.setProperty()函数操作，具体可以参考附件。</p>
<p>　　⑶ 如果找不到org.apache.commons.logging.Log系统属性，Logging接着在CLASSPATH中寻找log4j的类。如果找到了，Logging就假定应用要使用的是log4j。log4j本身的属性需要按照框架配置文件定义的方式进行，一般是通过log4j.properties文件正确配置。 </p>
<p>　　⑷ 如果上述查找均不能找到适当的Logging API，但应用程序正运行在JRE 1.4或更高版本上，则默认使用JRE 1.4的日志记录功能。 </p>
<p>　　⑸ 最后，如果上述操作都失败，则应用将使用内建的SimpleLog。SimpleLog把所有日志信息直接输出到System.err。 </p>
<p>了解了以上的过程就会明白为什么JCL+Log4J不再需要初始化，使用JCL+Log4J只需要在WEB-INF/lib下放置commons-logging.jar和log4j.jar包，在WEB-INF/classes下放置log4j.properties和commons-logging.properties（可选）文件，就可以在程序中随意的使用了。</p>
<p>为了方便大家了解详细情况，附件为Apusic下的一个使用案例。同样是个Servlet文件，只需要输入对Servlet进行访问就可以看到日志输出的全过程。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/203278#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 14 Jun 2008 18:09:06 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/203278</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/203278</guid>
      </item>
      <item>
        <title>Apusic AS的Web应用中调用Log4J的流程</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/203135" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/203135</a>&nbsp;
          发表时间: 2008年06月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>经常碰到项目中用Log4J，但是自己一直都没有认真去研究过Log4J的运行流程，看了许多资料讲得都是Log4J.properties怎么配置，但是Log4J启动&rarr;调用&rarr;输出的流程仍然不清楚，本文就准备对Log4J的详细启动过程进行介绍，使得大家可以更好的在Apusic中使用Log4J。</p>
<p>&nbsp;</p>
<p>1. 编写一个Servlet程序，目标是初始化Log4J的相关配置，具体内容参考附件中的Log4jInit.java程序，主要部分如下：</p>
<p>public class Log4jInit extends HttpServlet {</p>
<p>&nbsp;public void init() {<br />&nbsp;&nbsp;ServletContext context = getServletConfig().getServletContext();<br />&nbsp;&nbsp;Hierarchy hierarchy = new Hierarchy(new RootCategory(Level.DEBUG));</p>
<p>&nbsp;&nbsp;// 将hierarchy初始化后保存到context中，在Web应用的全局供其他Web代码使用。<br />&nbsp;&nbsp;context.setAttribute("hierarchy", hierarchy);</p>
<p>&nbsp;&nbsp;String prefix = getServletContext().getRealPath("/");<br />&nbsp;&nbsp;String file = getInitParameter("log4j-init-file");<br />&nbsp;&nbsp;// if the log4j-init-file is not set, then no point in trying<br />&nbsp;&nbsp;if (file != null) {&nbsp;&nbsp;&nbsp;// 增加hierarchy配置的内容<br />&nbsp;&nbsp;&nbsp;new PropertyConfigurator().doConfigure(prefix + file, hierarchy);<br />&nbsp;&nbsp;&nbsp;Logger logger = hierarchy.getLogger(Log4jInit.class.getName());<br />&nbsp;&nbsp;&nbsp;logger.info("Logging initialized for Hello.");<br />&nbsp;&nbsp;}<br />&nbsp;}</p>
<p>关键就是对Hierachy的初始化，并且保存到context中，供其他Web应用中的Java代码使用</p>
<p>2. 配置web.xml文件，对Log4jInit在Web应用加载过程中初始化</p>
<p>&nbsp;&lt;servlet&gt;<br />&nbsp;&nbsp;&lt;servlet-name&gt;log4j-init&lt;/servlet-name&gt;<br />&nbsp;&nbsp;&lt;servlet-class&gt;wombat.Log4jInit&lt;/servlet-class&gt;</p>
<p>&nbsp;&nbsp;&lt;init-param&gt;<br />&nbsp;&nbsp;&nbsp;&lt;param-name&gt;log4j-init-file&lt;/param-name&gt;<br />&nbsp;&nbsp;&nbsp;&lt;param-value&gt;WEB-INF/classes/log4j.properties&lt;/param-value&gt;<br />&nbsp;&nbsp;&lt;/init-param&gt;<br />&nbsp;&nbsp;&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />&nbsp;&lt;/servlet&gt;</p>
<p>3. 编写HelloServlet.java，在代码中使用Logger</p>
<p>&nbsp;public void init() throws ServletException {<br />&nbsp;&nbsp;ServletContext context = getServletConfig().getServletContext();<br />&nbsp;&nbsp;// 从context中取出hierarchy供本Servlet的Logger使用<br />&nbsp;&nbsp;Hierarchy hierarchy = (Hierarchy) context.getAttribute("hierarchy");</p>
<p>&nbsp;&nbsp;if (hierarchy == null) {<br />&nbsp;&nbsp;&nbsp;context.log("The Hello web-application is not properly intialized.");<br />&nbsp;&nbsp;} else {<br />&nbsp;&nbsp;&nbsp;logger = hierarchy.getLogger(HelloServlet.class.getName());</p>
<p>&nbsp;&nbsp; logger.info("HelloServlet initiation is OK！");<br />&nbsp;&nbsp;}<br />&nbsp;}</p>
<p>&nbsp;</p>
<p>因此，如果使用Log4J需要在代码中初始化Log4J的相关配置并保存到上下文中，同时配置信息写在web.xml中，并且正确提供log4j.properties文件，然后在代码中调用了Logger就可以输出日志信息了。</p>
<p>本例子的/hello.log一般会输出在应用所在盘的根目录下，开发人员可以根据自己的需要调整Log4J.properties文件就可以改变了。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/203135#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 13 Jun 2008 22:50:52 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/203135</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/203135</guid>
      </item>
      <item>
        <title>笔耕一百的痛苦</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/203099" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/203099</a>&nbsp;
          发表时间: 2008年06月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>开博时并没想过要写多少，但是写段时间后感觉不错。</p>
<p>首先，把过去的知识积累了下来，想用的时候通过网络一搜就能找到。</p>
<p>后来，发现可以通过网络与更多的朋友交流思想。</p>
<p>而且，当看到点击率增加，特别是有人表扬也极大满足了虚荣心呢。对于批评也有更好的承受力。</p>
<p>于是，使劲写到半夜三更，结果身体吃不消了，博客反而被放了很久，欲速则不达呀。</p>
<p>休养了很长一段时间后，重新检讨了过去的方式，计划每天笔耕一百字，坚持几天发现难呀。</p>
<p>一个是废话太多，百字根本不够用；其次，到家后累得连话都不想说更别提开电脑写博了。也深刻领会了古人所说笔耕的含义。</p>
<p>今天，计划为有时间就先在本子上写点，最后汇总到电脑里面，这样可以把等客户的小块时间利用起来了。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/203099#comments" style="color:red;">已有 <strong>2</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 13 Jun 2008 20:45:38 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/203099</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/203099</guid>
      </item>
      <item>
        <title>某企业捐款事件的危机处理之我见</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/196710" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/196710</a>&nbsp;
          发表时间: 2008年05月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>事件回放：０８年５月１２日，四川汶川大地震惊动世界，举国上下齐心协力，共渡难关。有钱的出钱，有力的出力。许多企业都积极主动的向灾区人民伸出援助之手。此时有家著名企业捐钱后被指数目与企业规模不相称，其实爱心本就不能金钱衡量，但是该企业负责人却以个人博客的方式予以反驳，并且用了一些不合适宜的表达，致使当事人和企业都受到巨大的舆论冲击。后来，为了挽救企业形象虽然进行了道歉，追加了巨额的捐款，但是仍被指为炒作和不诚心。到现在为止，此事并没有真正结束，有些情绪仍然在持续发酵，为何最初的一篇对话会引出如此多的后续问题，笔者认为后续的危机处理存在不足。</p>
<p>首先，道歉被指不真诚。当事人虽然通过媒体进行了正面回应，但是全文中仍有不少为自己解释的地方，当然面对巨大的舆论压力，有所解释也是人的正常反应。但是作为公众人物，且属于强势群体，过多的解释会让没有话语权的普通民众感到不真诚。</p>
<p>其实，这个时候最好的办法就是说声对不起，因为事情已经发生，无论何种理由给别人的伤害已经形成，道歉千次万次都无法改变事实，最好的办法就是除了&ldquo;对不起&rdquo;以外再不要再任何解释。</p>
<p>其次，公司后期捐款被指作秀。当事人同时是公司负责人，让公司巨额捐款其实是拿公司的钱为当事人的行为买单，目的无非是用来挽救受损的当事人及所代表的公司形象。当事人自己都说公司是股东的，不能随便动用，而公司虽然第一次捐得不多，但是已经向社会表达了公司的心意，再继续捐款除了承认前期真的捐错了，对受伤的民众心理没有任何补偿。</p>
<p>其实，这个时候要看当事人是否能够承担。为此次事件给公司和社会带来的负面情绪引咎辞职（至少可以学诸葛先生官降三级），因为当事人是公司的负责人，属于公众人物，一言一行代表着公司。离开现在的岗位可以使负面情绪对公司的冲击减小到最少。</p>
<p>最后，就是负责人带领团队冲到一线。其实这个问题只是前面问题的延续，如果没有真正的道歉和对后果的承担，后续的作为只能让人产生怀疑。如果当事人真的放弃现在的职位，而作为一个普通志愿者参加到一线的重建工作中来，放下过去的成就和错误从头开始，笔者认为一定会得到大家的理解，甚至对自己也是个新的开始。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/196710#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 25 May 2008 15:48:04 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/196710</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/196710</guid>
      </item>
      <item>
        <title>J2EE应用服务器Apusic AS在HP-UX上调优时使用的工具列表</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/196601" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/196601</a>&nbsp;
          发表时间: 2008年05月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>开发人员写程序一般都在Windows下，主要还是方便。但是许多问题又都是上线后才能发现，特别是在开发过程不健全的情况下，许多都是边用边解决问题，那么如果部署到IBM或者HP的小机后，如何跟踪和调试呢？</p>
<p>可以去下载HP-UX提供的文档，http://www.docs.hp.com/en/5992-1918/5992-1918.pdf</p>
<p>里面还有相关工具的下载地址。</p>
<p>这里把主要的调优的工具做个列表，顺便简单介绍一下功能，以后我会将熟悉的工具再分别介绍。</p>
<p>★　Ctrl-Break Handler</p>
<p>作用：具备与Windows下一样的功能，实现Dump Thread功能。</p>
<p>用法：kill -3 &lt;pid&gt;　或者　-XX:+HeapDump or -XX:+HeapDumpOnCtrlBreak</p>
<p>★　Fatal Error Log (hs_err_pid&lt;pid&gt;.log)</p>
<p>作用：当发生严重错误时，系统自动在应用运行目录下创建以pid为模式的日志文件；</p>
<p>用法：系统自动处理</p>
<p>★　HPjconfig</p>
<p>作用：可视化工具，根据应用的情况推荐和调整HP的核心参数；</p>
<p>用法：java -jar HPjconfig.jar</p>
<p>★　HPjmeter</p>
<p>作用：可视化工具，分析应用的性能瓶颈，跟踪方法调用次数、CPU占用率和周期，线程的时间消耗和进程中的线程数；</p>
<p>用法：/opt/hpjmeter/bin/hpjmeter</p>
<p>备注：HPjmeter用法复杂，使用前需仔细阅读使用指南</p>
<p>★　HPjtune</p>
<p>作用：可视化工具，分析应用运行期垃圾收集（GC）的情况，从3.0开始合并到HPjmeter；</p>
<p>★　jConsole</p>
<p>作用：可视化工具，分析JVM的运行状态；</p>
<p>用法：jConsole 直接运行，输入连接字符串，具体可以参考SUN的指南或本Blog后面的使用说明</p>
<p>★　jstat／jstatd</p>
<p>作用：统计监测工具，连接到JVM上收集相关数据；jstatd是远程连接</p>
<p>用法：jstat -gc &lt;pid&gt; [interval] [times]</p>
<p>★　visualgc</p>
<p>作用：可视化工具，监测JVM的GC、Compiler和Class Loader，可以监控本地和远程的</p>
<p>用法：visualgc vmid [interval]</p>
<p>★　GlancePlus</p>
<p>作用：系统性能监视和分析工具。</p>
<p>★　sar</p>
<p>作用：报告系统活动，包括：CPU、I/O、context switches,interrupts, page faults, and other kernel actions.</p>
<p>★　vmstat</p>
<p>作用：报告process, virtual memory, trap, and CPU</p>
<p>★　iostat</p>
<p>作用：报告每个活动Disk的I/O情况</p>
<p>★　swapinfo</p>
<p>作用：提供device和file system 页面空间</p>
<p>★　top</p>
<p>作用：显示系统中主要进程，定期更新信息。根据CPU使用情况排列进程。</p>
<p>★　netstat</p>
<p>作用：显示网络接口和协议的统计结果以及网络相关的数据结构，包括：packet traffic, connections, error　rates, and more</p>
<p>&nbsp;</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/196601#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 24 May 2008 23:10:59 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/196601</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/196601</guid>
      </item>
      <item>
        <title>玩游戏中体会到的平衡</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/195829" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/195829</a>&nbsp;
          发表时间: 2008年05月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>过了三十岁后，开始关注各种平衡的东西。时间用于工作与生活的平衡，程序设计复杂与简单的平衡，独自承担与团队协作的平衡。。。一直感觉平衡不容易把握，好像总在两个极点左右摇摆，直到这两天玩手机游戏时突然有所感悟。<br />游戏是消除屏幕上横平坚直堆着的许多小球，它们由五种颜色组成，每两个相同颜色在一起就可以消掉，相同颜色的越多消除时得分越高，每消完一列后就会从右边加入新的一列。游戏设计得并不复杂，但是最初玩的时候因为其他游戏的惯性，总想把桌面的全部消完，结果屏幕上剩下的小球没有同色在一起的，游戏结束，得分一直不高。后来努力消列增加新的，这样保证总有东西消，屏幕上的小球一直很多，但过多的选择使决策过程非常复杂，很难将更多同色的拼在一起，结果是耗时过长，到后面没有体力而频频出现失误，导致游戏结束也没得到更高的分。后来，我学会控制游戏的发展，当屏幕上小球太少时，我会消几个列增加小球数目，当屏幕小球过多时，我又会不求高分而将屏幕小球数量尽量减少，从而降低选择成本，保存体力。结果，只要有力气玩就可以一直不死。其实，我想从游戏中推广到工作中。<br />从工作本身看。先要了解自己工作强度大约是多少，当工作少时就应该主动与领导请缨，增加工作量提升自己在公司的价值；当工作太多时，就需要控制工作内容，适当地拒绝部分工作，目的是将手里的工作做好，而不是简单的完成工作，那样对不起客户和公司，更对不起自己的宝贵时间。<br />从销售角度看。要了解自己手里多少商机运作比较有把握，当商机不足时应该努力扩大商机，为未来的发展打下基础；当商机过多时应该果断放弃部分，为做好现在的项目保证时间和精力。<br />从技术角度看。当技术学习遇到瓶颈，感觉不到学习的方向时，需要增加对不同技术的涉猎，目的是扩大自己的知识面，从而寻找新的突破点；当进入新天地，感觉什么都想学，什么都需要学时，必须把握重点，利用自己宝贵的时间学好最紧迫的东西。 </p>
<p><a href="http://www.blogjava.net/zhuyuanxiang/archive/2008/05/22/202280.html" class="titlelink" id="Editor_Results_rprSelectionList_ctl01_LinkTitle"></a></p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/195829#comments" style="color:red;">已有 <strong>6</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 22 May 2008 23:00:38 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/195829</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/195829</guid>
      </item>
      <item>
        <title>项目管理之我见 </title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/195050" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/195050</a>&nbsp;
          发表时间: 2008年05月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>伴随着我国信息化的发展，项目管理越来越成为项目成功的关键问题。许多项目配备了足够优秀的人手，仍然以失败告终，根本原因就是没有良好的管理，大家都在努力工作，但是每个人却冲着不同的方向，结果可想而知。那么如何才能有效的管理呢？<br />首先，控制需求。<br />采集需求的书多如牛毛，每个人都提出了自己的观点。作者认为控制需求中主要把握好以下三点：<br />● 充分阅读招标方案中客户的要求，最好将之细化成具体的、量化的、可操作的目标。当然最初的阅读无法达到细化的需要，但是充分理解招投标方案是对行业知识最快的学习方法，还需要通过不同侧面去了解所做项目的行业背景，这就是俗话所说的做功课。；<br />● 充分认识&ldquo;客户永远是对的&rdquo;。刚接手项目时，没有行业经验必须先虚心向客户学习。确定需求时，还必须具备专家的能力理解和引导客户需求。与客户最危险的沟通方式就是问：这个项目想做点啥？不设条件的让客户去想，要不客户不理解信息化项目说不出东西，要不就是客户终于有个表达自己的机会说出无数的需求，使项目范围无限扩大。其实，这些都是因为自己没有对项目充分认识，自己不懂当然会被别人牵着鼻子走了。；<br />● 充分理解需求变更的现实意义。软件工程早期人们极端的认为客户无理地变更需求导致项目失败，但是随着极限编程概念的推广和软件开发效率的不断提升，大家也越来越理解需求变更的合理性。但是，管理需求变更仍然是非常重要的工作。如果担心得罪客户而一味的迁就，或者硬顶客户并且所有事情都找他签字，结果都会给项目推进带来不必要的麻烦。因此，确定合理的变更流程，并且引导客户认识并承担需求变更的成本与风险。就能够有效规避需求变更本身给项目带来的冲击。<br />例如：作者参与过的公安项目，以前根本没有公安行业的背景，于是经历过一个月的痛苦学习阶段，然后才具备了与客户正面沟通的实力，指出客户需求中与本次项目中有所冲突的地方，并且为客户提出其他的解决方案，最终协助客户找到项目完工的真正目标，促使拖了近一年的项目用两个月的时间完成了收尾、上线、初验并收款。而项目的成功推进根本原因是控制好需求，清晰了目标，有了方向工作就好做了。</p>
<p>其次，建立团队。<br />一个优秀的团队一定会有一个优秀的项目经理，项目经理可以说是整个团队的灵魂，因此一个项目要成功必须要找到合适的项目经理。<br />项目经理会负责选择合适的团队成员将团队组织在一起，团队至少包括：技术负责人、软件开发人员、软件测试人员，比例是1:2:1，这个配置是根据中国情况提供的最低标准。中国很少能够组织完整的项目团队，资源的严重不足导致团队人员只能按最低配置完成。由比例可以得知团队至少需要5个人，这是团队组织标准7&plusmn;2的最低要求，这样的团队才是有战斗力的团队。<br />由于项目太多，许多公司连这样的团队都无法组织。如果是这样，作者建议宁愿一个团队接多个项目，也不要一个项目只配1～2个人。因为这是团队建设中的第二个重要问题：分工。术有专攻，自古就已经得到认同。同时，现代科学技术越来越复杂，没有人是全才。还有，公司不可能养得起许多个高手。因此，这样的团队由：项目经理＋技术负责人＋技术熟手＋技术生手＋测试人员是一个非常好的搭配，大大减低公司在人员上的成本投入，不同层面的人员搭配可以使项目中各种工作都有相应的人员去应对，同时不同层次的工程师配合也使知识在项目中得到有效传递，而生手的成熟只有靠项目完成，有老手帮带也使项目质量容易管控。同时可以保证每个人在项目中有事做，有成长的机会，有成就感。</p>
<p>然后，制定计划。<br />&ldquo;凡事预则立，不预则废&rdquo;，因此没有计划的工作失败是难免的事情，成功完全是碰运气。但是制定计划本身也是一件技术活，在计划之前一定要先完成需求准备工作，就是为项目确定目标，没有目标也就无从谈起计划了。只有目标本身是可量化的，计划才能够有效制定出来。小时候经常会制定目标考100分，现在发现那不叫目标叫愿望。目标是对项目进行有效评估，了解具体的工作是哪些，大致需要多久时间才，确认目标实现后项目就可以结束。这些才是项目的真正目标，并以每个目标评估的时间消耗为基础，制定项目计划，项目计划出来后直接乘2就是最终项目的完成时间表。但是现实是项目时间表根本没法获得公司或者客户的认可，时间肯定会被大大压缩，这时就需要对计划中的目标排优先级，重新阅读每个目标，如果是可做可不做的先删除，直到留下来不得不做的，再重新评估时间，基本上会比实际项目时间短很多，但是以这个为基础开始项目实施吧。<br />作者参与过一个公司内部项目，将地理信息系统应用从J2EE平台移植到DotNET上，技术风险比较多，人员也是临时组建的，本来三个月的项目最后被压缩成一个半月，但是项目最终完成并通过公司和投资人的验收。因为，从开始就排定了项目目标的优先级，并且作为项目经理时刻提醒组员关注项目前进方向；其次，一直把应用集成排在项目的第一目标，在三周左右项目就已经可以上线运行，于是测试工作与开发工作保持同步展开；最后，与客户（领导和投资人）保持紧密沟通，时刻报知项目进度和完成的内容，使客户了解项目是否提供了他所需要的最基础的功能，以及真正理解项目未实现的目标原因，并能够提早接受这样的现实情况，为项目最终验收奠定了基础。</p>
<p>最后，有效执行。<br />执行力是许多管理者关注的问题，常常感叹为什么有Power就推不动事情的前进呢？其实，就如国家实力一样，分硬实力和软实力。管理者拥有的只是公司提供的这个Power叫硬实力，但是还需要在工作中积累自己的软实力，通过增强团队凝聚力、提升团队文化、创造团队成员的个人发展环境来增强自己的软实力。有了软实力，团队成员更愿意付出努力来为团队目标奋斗，许多事情自然不需要花大力气推动，而有了水到渠成的感觉。</p>
          <br/><br/>
          <span style="color:red;">
            <a href="http://zhuyuanxiang.javaeye.com/blog/195050#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 20 May 2008 23:12:41 +0800</pubDate>
        <link>http://zhuyuanxiang.javaeye.com/blog/195050</link>
        <guid>http://zhuyuanxiang.javaeye.com/blog/195050</guid>
      </item>
      <item>
        <title>对汶川地震的纪念</title>
        <author>zhuyuanxiang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://zhuyuanxiang.javaeye.com">zhuyuanxiang</a>&nbsp;
          链接：<a href="http://zhuyuanxiang.javaeye.com/blog/194665" style="color:red;">http://zhuyuanxiang.javaeye.com/blog/194665</a>&nbsp;
          发表时间: 2008年05月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>因为不会写纪念性的文章，所以也没准备记录这次地震。本来今天见客户进行技术交流也有许多感想，但是看完新闻联播，自己深深地被这次全国默哀震撼了。</p>
<p>看到全国13亿人能够停止自己的事情，发自内心的为汶川地震中逝去的生命默哀，使我不禁想起&ldquo;二人同心，其得断金&rdquo;，现在全国13亿人同心协力，没有什么困难不能克服。</p>
<p>今天刚见客户时就聊到地震的问题，因为地震的时候我在成都，所以对方非常关心的问我情况。成都本身受地震影响比较小，中间出现的一些情况主要还是心理层面的东西比较多，包括传言的影响、余震的恐惧等等。而我本人是在新疆长大，那里也是地震多发地区，我受过地震培训也进行过地震演习，所以这次地震对我的影响很小，但是成