<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>jamesby</title>
    <description></description>
    <link>http://jamesby.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>weblogic.xml文件代码示例</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/184348" style="color:red;">http://jamesby.javaeye.com/blog/184348</a>&nbsp;
          发表时间: 2008年04月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN" "http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">
&lt;weblogic-web-app>
  &lt;session-descriptor>
    &lt;session-param>
	&lt;param-name>CookieName&lt;/param-name>
	&lt;param-value>xbsite_cookiename&lt;/param-value>     
   &lt;/session-param>
   &lt;session-param>
	&lt;param-name>CookiePath&lt;/param-name>
	&lt;param-value>/xbsite&lt;/param-value>     
   &lt;/session-param>
    &lt;session-param>
      &lt;param-name>InvalidationIntervalSecs&lt;/param-name>
      &lt;param-value>120&lt;/param-value>
    &lt;/session-param>
    &lt;session-param>
      &lt;param-name>TimeoutSecs&lt;/param-name>
      &lt;param-value>3600&lt;/param-value>
    &lt;/session-param>
  &lt;/session-descriptor>

  &lt;jsp-descriptor>
    &lt;jsp-param>
      &lt;param-name>encoding&lt;/param-name>
      &lt;param-value>GBK&lt;/param-value>
    &lt;/jsp-param>
    &lt;jsp-param>
      &lt;param-name>pageCheckSeconds&lt;/param-name>
      &lt;param-value>120&lt;/param-value>
    &lt;/jsp-param>
	&lt;jsp-param>
	  &lt;param-name>compilerSupportsEncoding&lt;/param-name>
      &lt;param-value>true&lt;/param-value>
    &lt;/jsp-param>
    &lt;jsp-param>
      &lt;param-name>verbose&lt;/param-name>
      &lt;param-value>false&lt;/param-value>
    &lt;/jsp-param>
  &lt;/jsp-descriptor>

  &lt;container-descriptor>
    &lt;servlet-reload-check-secs>-1&lt;/servlet-reload-check-secs>
    &lt;resource-reload-check-secs>30&lt;/resource-reload-check-secs>
    &lt;single-threaded-servlet-pool-size>100&lt;/single-threaded-servlet-pool-size>
  &lt;/container-descriptor>

  &lt;context-root>/xbsite&lt;/context-root>
&lt;/weblogic-web-app></pre>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/184348#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 19 Apr 2008 10:44:28 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/184348</link>
        <guid>http://jamesby.javaeye.com/blog/184348</guid>
      </item>
      <item>
        <title>java 运行版本问题</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/164958" style="color:red;">http://jamesby.javaeye.com/blog/164958</a>&nbsp;
          发表时间: 2008年02月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在JDK 5.0 上编译好的class,即使未用到任何5.0的新功能，也不能在 JDK 1.4.3上运行。
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/164958#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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>Tue, 26 Feb 2008 08:33:23 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/164958</link>
        <guid>http://jamesby.javaeye.com/blog/164958</guid>
      </item>
      <item>
        <title>sqlserver 2000 1433 端口未打开的问题</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/164957" style="color:red;">http://jamesby.javaeye.com/blog/164957</a>&nbsp;
          发表时间: 2008年02月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          需要安装SqlServer 2000 SP4
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/164957#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 26 Feb 2008 08:32:01 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/164957</link>
        <guid>http://jamesby.javaeye.com/blog/164957</guid>
      </item>
      <item>
        <title>我的一次weblogic 8升级到weblogic9遇到的问题.</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/76181" style="color:red;">http://jamesby.javaeye.com/blog/76181</a>&nbsp;
          发表时间: 2007年04月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>1、web应用的乱码问题。</strong><br />原来的基于weblogic8的应用,后来部署到weblogic 9 上面，所有的web应用都能正常部署，而且不需要经过太多修改，就是有一个应用出现乱码，原因是我直接在JSP文件中写汉字，而没有使用国际化。后来将weblogic.xml配置成如下方式解决了该问题：<br /><pre name="code" class="java">&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN" "http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">
&lt;weblogic-web-app>  
&lt;jsp-descriptor>    
	&lt;jsp-param>     
 		&lt;param-name>encoding&lt;/param-name>      
 		&lt;param-value>GBK&lt;/param-value>  
 	&lt;/jsp-param> 
 	&lt;jsp-param>
         &lt;param-name>compilerSupportsEncoding&lt;/param-name>
         &lt;param-value>true&lt;/param-value>
    &lt;/jsp-param>
  &lt;/jsp-descriptor> 
  &lt;context-root>/james&lt;/context-root>
&lt;/weblogic-web-app></pre><br /><br /><strong>2、jsp的相对路径问题<br /><br />jsp的前面有如下所示声明代码：</strong><pre name="code" class="java">&lt;%@ include  file="include/header.jsp" %></pre><br /><br />如果在weblogic 8 中，即使该相对当前jsp的文件不存在，也就是说上面的路径有问题，也不会报任何错误。<br /><br />而在9.2上部署则不允许通过。<br /><br /><strong>3、EJB 部署问题</strong><br /><br />这个实际与webloigc的版本无关，EJB使用了JNI调用一个dll，而部署好以后，当访问的时候老是报如下错误：<br /><br /><pre name="code" class="java"> java.rmi.RemoteException: EJB Exception: ; nested exception is: 
	java.lang.NoClassDefFoundError: com/jamesby/SessionBean_n66q2o_Impl
	at weblogic.ejb.container.internal.EJBRuntimeUtils.throwRemoteException(EJBRuntimeUtils.java:95)
	at weblogic.ejb.container.internal.BaseEJBObject.handleSystemException(BaseEJBObject.java:724)
	at weblogic.ejb.container.internal.BaseEJBObject.handleSystemException(BaseEJBObject.java:681)
	at weblogic.ejb.container.internal.BaseEJBObject.preInvoke(BaseEJBObject.java:229)</pre><br /><br />搞的我百思不得其解，而这个错误只有发布到服务器上才出现如上错误，而本地没有任何问题，后在服务器建立一个Develop Mode方式的domain，后启动server报一个又一个的dll 找不到。而product mode方式不会报这个错误，因为我的系统需要通过JNI调用一个DLL,而该DLL需要访问一个C/S模式的软件的客户端的dll。而客户端我并没有安装。<br /><br />我气愤地是对于Product mode weblogic竟然如此严重的错误也不报,而报什么class 找不到,害的我忙了好长时间。<br /><br /><strong>4、sqlserver 2005数据库驱动问题</strong><br /><br />用微软发布1.1的驱动,Bea的Connection Pool出现如下问题:<br /><br /><pre name="code" class="java">com.microsoft.sqlserver.jdbc.SQLServerException: 服务器无法继续执行该事务。说明: 3c000005b9。   
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Lcom.microsoft.sqlserver.jdbc.SQLServerConnection;Lcom.microsoft.sqlserver.jdbc.IOBuffer;Ljava.lang.String;Lcom.microsoft.sqlserver.jdbc.StreamError;Z)V(Unknown Source)   
    at com.microsoft.sqlserver.jdbc.IOBuffer.processPackets(Lcom.microsoft.sqlserver.jdbc.SQLServerConnection;[Lcom.microsoft.sqlserver.jdbc.PacketRequestor;ILjava.lang.String;Z)Lcom.microsoft.sqlserver.jdbc.StreamPacket;(Unknown Source)   
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult()Z(Unknown Source)   
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteStatement(Lcom.microsoft.sqlserver.jdbc.SQLServerStatement$StatementExecutionRequest;Lcom.microsoft.sqlserver.jdbc.TDSWriter;)V(Unknown Source)   
    at com.microsoft.sqlserver.jdbc.SQLServerStatement$StatementExecutionRequest.executeStatement(Lcom.microsoft.sqlserver.jdbc.TDSWriter;)V(Unknown Source)   
    at com.microsoft.sqlserver.jdbc.CancelableRequest.execute(Lcom.microsoft.sqlserver.jdbc.TDSWriter;)V(Unknown Source)   
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeRequest(Lcom.microsoft.sqlserver.jdbc.ExecutableRequest;I)V(Unknown Source)   
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeQuery(Ljava.lang.String;)Ljava.sql.ResultSet;(Unknown Source)   
    at weblogic.jdbc.wrapper.Statement.executeQuery(Statement.java:412) </pre><br /><br />原因不清楚,也懒的找,后来改用Bea的驱动,到目前为止比较正常.<br /><br /><strong>5、JSP文件名大小写问题</strong><br />系统部署在windows操作系统，系统的web层采用Spring MVC 并采用ResourceBundleViewResolver,urlMapping 采用SimpleUrlHandlerMapping,本来在weblogic8 上的时候如果在jamesby.properties配置为viewName.url=/WEB-INF/jsp/Abc.jsp<br />而实际的jsp的文件名为abc.jsp的时候,是没有任何问题的.<br /><br />而在weblogic 9上则文件名必须为Abc.jsp才可以,否则报404错误.<br /><br />当然unix或者linux是区分大小写肯定有这个要求的.但是windows系统的weblogic 9平台也有这个要求<br /><br /><br />以上就是我的一次升级经历，希望对大家有帮助。另外weblogic 9耗资源好高,本来PC跑weblogic8很轻松的,跑weblogic 9则根本跑不动.
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/76181#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 29 Apr 2007 18:17:41 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/76181</link>
        <guid>http://jamesby.javaeye.com/blog/76181</guid>
      </item>
      <item>
        <title>关于手机浏览器的问题？</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/72816" style="color:red;">http://jamesby.javaeye.com/blog/72816</a>&nbsp;
          发表时间: 2007年04月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          现在有一个新的需求，本来目前的基于web的软件开发已经完成，但是目前有新的需求，就是要求该web系统能够在手机上操作。<br /><br />目前的思路仍然是开发一个支持手机浏览器的web层。<br /><br />现在就是有下面几方面的需求不是很了解，希望大家给些意见：<br /><br />1、手机浏览器对表格的支持怎么样？或者说是否支持表格。<br />2、手机浏览器对字体大小是不是不需要设置？<br />3、手机浏览器对js的支持怎么样？<br /><br />其实还有很多这方面的问题。就是希望能够得到关于手机浏览器对html和js的支持情况。<br /><br />先在这里谢谢大家了。
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/72816#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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 Apr 2007 12:07:17 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/72816</link>
        <guid>http://jamesby.javaeye.com/blog/72816</guid>
      </item>
      <item>
        <title>JDK的动态代理是如何实现的?</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/71036" style="color:red;">http://jamesby.javaeye.com/blog/71036</a>&nbsp;
          发表时间: 2007年04月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          用Spring大概有3个月,一直都是张口AOP,闭口AOP,但是Spring的AOP具体是怎么实现的,现在也不是十分清楚.<br /><br />只知道可以用JDK的动态代理,基于接口,或者是cglib方式字节码增强.目前对JDK的动态代理方式不是很理解,固拿出来探讨下,我知道这应该是个新手贴,但还是请大家给点意见.如果真正理解了动态代理,那么对基于Spring AOP出现的各种现象就比较容易理解了.<br /><br />先贴上一段代码.<br /><br /><pre name="code" class="java">package com.jamesby.proxy;
public interface CarCompany {

	public void makeCar(); 
	public void abc();
}

package com.jamesby.proxy;

public class CarCompanyImpl implements CarCompany {
	public void makeCar() {
		System.out.println("Company A make a car!");
		abc();
	}
	public void abc()
	{
		System.out.println("abc is invoked!");
	}
}

package com.jamesby.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class CarCompanyHandler implements InvocationHandler  {
	CarCompany com;
	public CarCompanyHandler(CarCompany com) {
		this.com = com;
	}
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
			System.out.println("time1:" + System.currentTimeMillis());
			method.invoke(this.com, new Class[] {});
			System.out.println("time2:" + System.currentTimeMillis());
		return null;
	}
}

package com.jamesby.proxy;

import java.lang.reflect.Proxy;

public class Test {
	public static void main(String[] arg) {
		CarCompanyImpl a = new CarCompanyImpl();
		CarCompanyHandler handler = new CarCompanyHandler(a);
		// 产生一个新的代理类
		CarCompany com = (CarCompany) Proxy.newProxyInstance(Test.class
				.getClassLoader(), new Class[] { CarCompany.class }, handler);
		com.makeCar();
	}
}</pre><br /><br /><br />从以上代码可以看出在调用com.makeCar()的时候动态代理会生效,而在makeCar()方法中调用abc()的时候并不会进行动态代理.<br /><br />猜测到底JDK是如何实现动态代理的?<br />1.基于JDK的反射机制,通过JDK调用handler的method.invoke(this.com, new Class[] {});实现对最终方法的调用,前后各有代码也有点Decorator的味道!<br /><br />2.也是我比较模糊的一点<br /><pre name="code" class="java">		CarCompany com = (CarCompany) Proxy.newProxyInstance(Test.class
				.getClassLoader(), new Class[] { CarCompany.class }, handler);
		com.makeCar();</pre><br /><br />也就是动态代理JDK到底是如何实现的?<br />JDK的动态代理并没有生成具体的类,她只是在运行中起动态调用目标类的作用,那么代码<br /><pre name="code" class="java">CarCompany com = (CarCompany) Proxy.newProxyInstance(Test.class
				.getClassLoader(), new Class[] { CarCompany.class }, handler);</pre><br />究竟做了什么,是将CarCompany注册到JDK的某个地方,当调用com.makeCar()的时候JDK到注册的地方去寻找,发现有注册就进行动态代理?
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/71036#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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 Apr 2007 09:06:35 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/71036</link>
        <guid>http://jamesby.javaeye.com/blog/71036</guid>
      </item>
      <item>
        <title>Weblogic下的自动任务</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/67610" style="color:red;">http://jamesby.javaeye.com/blog/67610</a>&nbsp;
          发表时间: 2007年04月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">package com.jamesby.listener;

import java.util.*;
import javax.management.*;
import javax.naming.Context;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import weblogic.management.timer.Timer;

public class AutoTaskManager implements HttpSessionListener,
		HttpSessionAttributeListener, NotificationListener,
		ServletContextListener {
	private static final Log logger = LogFactory.getLog(AutoTaskManager.class);

	private int count;

	private ServletContext context = null;

	public static final long PERIOD = Timer.ONE_DAY;

	private long period;

	private boolean debug;

	private Timer timer;

	private Integer notificationId;

	public void contextInitialized(ServletContextEvent event) {
		try {
			initParams(event);
			timer = new Timer();
			timer.addNotificationListener(this, null, "Message Broker ");
			Calendar cal = Calendar.getInstance();
			Date timerTriggerAt = cal.getTime();
			notificationId = timer.addNotification("Timer Type",
					"Timer Message", this, timerTriggerAt, period);
			timer.start();
		} catch (Exception e) {

		}
	}

    public void initParams(ServletContextEvent event) {
        ServletContext ctx = event.getServletContext();
        try {
            period = PERIOD;
        } catch (Exception e) {
            period = Timer.ONE_DAY;
            e.printStackTrace();
        }
    }

    public void contextDestroyed(ServletContextEvent event) {
        try {
            timer.stop();
            timer.removeNotification(notificationId);
        } catch (InstanceNotFoundException e) {
            e.printStackTrace();
        }
    }

    public void handleNotification(Notification notif, Object handback) {
    }

    public void attributeAdded(HttpSessionBindingEvent se) {

    }
    
    public void attributeRemoved(HttpSessionBindingEvent se) {
 	
    }

    public void attributeReplaced(HttpSessionBindingEvent se) {

    }

    public void sessionCreated(HttpSessionEvent se) {
    }

    public void sessionDestroyed(HttpSessionEvent se) {
    }
}</pre>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/67610#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 03 Apr 2007 14:13:19 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/67610</link>
        <guid>http://jamesby.javaeye.com/blog/67610</guid>
      </item>
      <item>
        <title>是用SmartUpload进行文件上传</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/67608" style="color:red;">http://jamesby.javaeye.com/blog/67608</a>&nbsp;
          发表时间: 2007年04月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">package com.jamesby.file.servlet;

public class UpLoadServlet extends HttpServlet {
	private static Log log = LogFactory.getLog(UpLoadServlet.class);
	
	private ServletConfig config;
	
	final public void init(ServletConfig config) throws ServletException {
		this.config = config;
	}
	
	final public ServletConfig getServletConfig() {
		return config;
	}
	
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws
	ServletException, IOException {
		doPost(request, response);
	}


	public void doPost(HttpServletRequest request, HttpServletResponse response) throws
	ServletException, IOException {
		try {
			SmartUpload su = new SmartUpload();
			
			su.initialize(config, request, response);
			
			su.setMaxFileSize(1024 * 1024 * 4); //4M
			
			su.upload();
			
			String paramValue = su.getRequest().getParameter("paramName");
			
			String path = "d:/upload";
			for (int i = 0; i &lt; su.getFiles().getCount(); i++) {
				
				com.jspsmart.upload.File file = su.getFiles().getFile(i);
				
				String fileName = file.getFileName();
				
				if (!file.isMissing())  file.saveAs(path + "/"+fileName,SmartUpload.SAVE_PHYSICAL);
				else continue;
			}
			return null;
		} catch (Exception ex) {
		
		}
	}
}</pre>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/67608#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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>Tue, 03 Apr 2007 14:06:30 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/67608</link>
        <guid>http://jamesby.javaeye.com/blog/67608</guid>
      </item>
      <item>
        <title>文件下载Servlet</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/67604" style="color:red;">http://jamesby.javaeye.com/blog/67604</a>&nbsp;
          发表时间: 2007年04月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">package com.jamesby.action;

public class FileDownloadServlet extends HttpServlet {
	private static Log log = LogFactory.getLog(FileDownloadServlet.class);
	private static HashMap _MIME_TYPE_MAP = new HashMap();
	static {
		_MIME_TYPE_MAP.put("ez", "application/andrew-inset");
		_MIME_TYPE_MAP.put("hqx", "application/mac-binhex40");
		_MIME_TYPE_MAP.put("cpt", "application/mac-compactpro");
		_MIME_TYPE_MAP.put("doc", "application/msword");
		_MIME_TYPE_MAP.put("bin", "application/octet-stream");
		_MIME_TYPE_MAP.put("dms", "application/octet-stream");
		_MIME_TYPE_MAP.put("lha", "application/octet-stream");
		_MIME_TYPE_MAP.put("lzh", "application/octet-stream");
		_MIME_TYPE_MAP.put("exe", "application/octet-stream");
		_MIME_TYPE_MAP.put("class", "application/octet-stream");
		_MIME_TYPE_MAP.put("so", "application/octet-stream");
		_MIME_TYPE_MAP.put("dll", "application/octet-stream");
		_MIME_TYPE_MAP.put("oda", "application/oda");
		_MIME_TYPE_MAP.put("pdf", "application/pdf");
		_MIME_TYPE_MAP.put("ai", "application/postscript");
		_MIME_TYPE_MAP.put("eps", "application/postscript");
		_MIME_TYPE_MAP.put("ps", "application/postscript");
		_MIME_TYPE_MAP.put("smi", "application/smil");
		_MIME_TYPE_MAP.put("smil", "application/smil");
		_MIME_TYPE_MAP.put("mif", "application/vnd.mif");
		_MIME_TYPE_MAP.put("xls", "application/vnd.ms-excel");
		_MIME_TYPE_MAP.put("ppt", "application/vnd.ms-powerpoint");
		_MIME_TYPE_MAP.put("wbxml", "application/vnd.wap.wbxml");
		_MIME_TYPE_MAP.put("wmlc", "application/vnd.wap.wmlc");
		_MIME_TYPE_MAP.put("wmlsc", "application/vnd.wap.wmlscriptc");
		_MIME_TYPE_MAP.put("bcpio", "application/x-bcpio");
		_MIME_TYPE_MAP.put("vcd", "application/x-cdlink");
		_MIME_TYPE_MAP.put("pgn", "application/x-chess-pgn");
		_MIME_TYPE_MAP.put("cpio", "application/x-cpio");
		_MIME_TYPE_MAP.put("csh", "application/x-csh");
		_MIME_TYPE_MAP.put("dcr", "application/x-director");
		_MIME_TYPE_MAP.put("dir", "application/x-director");
		_MIME_TYPE_MAP.put("dxr", "application/x-director");
		_MIME_TYPE_MAP.put("dvi", "application/x-dvi");
		_MIME_TYPE_MAP.put("spl", "application/x-futuresplash");
		_MIME_TYPE_MAP.put("gtar", "application/x-gtar");
		_MIME_TYPE_MAP.put("hdf", "application/x-hdf");
		_MIME_TYPE_MAP.put("js", "application/x-javascript");
		_MIME_TYPE_MAP.put("skp", "application/x-kn");
		_MIME_TYPE_MAP.put("skd", "application/x-kn");
		_MIME_TYPE_MAP.put("skt", "application/x-kn");
		_MIME_TYPE_MAP.put("skm", "application/x-kn");
		_MIME_TYPE_MAP.put("latex", "application/x-latex");
		_MIME_TYPE_MAP.put("nc", "application/x-netcdf");
		_MIME_TYPE_MAP.put("cdf", "application/x-netcdf");
		_MIME_TYPE_MAP.put("sh", "application/x-sh");
		_MIME_TYPE_MAP.put("shar", "application/x-shar");
		_MIME_TYPE_MAP.put("swf", "application/x-shockwave-flash");
		_MIME_TYPE_MAP.put("sit", "application/x-stuffit");
		_MIME_TYPE_MAP.put("sv4cpio", "application/x-sv4cpio");
		_MIME_TYPE_MAP.put("sv4crc", "application/x-sv4crc");
		_MIME_TYPE_MAP.put("tar", "application/x-tar");
		_MIME_TYPE_MAP.put("tcl", "application/x-tcl");
		_MIME_TYPE_MAP.put("tex", "application/x-tex");
		_MIME_TYPE_MAP.put("texinfo", "application/x-texinfo");
		_MIME_TYPE_MAP.put("texi", "application/x-texinfo");
		_MIME_TYPE_MAP.put("t", "application/x-troff");
		_MIME_TYPE_MAP.put("tr", "application/x-troff");
		_MIME_TYPE_MAP.put("roff", "application/x-troff");
		_MIME_TYPE_MAP.put("man", "application/x-troff-man");
		_MIME_TYPE_MAP.put("me", "application/x-troff-me");
		_MIME_TYPE_MAP.put("ms", "application/x-troff-ms");
		_MIME_TYPE_MAP.put("ustar", "application/x-ustar");
		_MIME_TYPE_MAP.put("src", "application/x-wais-source");
		_MIME_TYPE_MAP.put("xhtml", "application/xhtml+xml");
		_MIME_TYPE_MAP.put("xht", "application/xhtml+xml");
		_MIME_TYPE_MAP.put("zip", "application/zip");
		_MIME_TYPE_MAP.put("au", "audio/basic");
		_MIME_TYPE_MAP.put("snd", "audio/basic");
		_MIME_TYPE_MAP.put("mid", "audio/midi");
		_MIME_TYPE_MAP.put("midi", "audio/midi");
		_MIME_TYPE_MAP.put("kar", "audio/midi");
		_MIME_TYPE_MAP.put("mpga", "audio/mpeg");
		_MIME_TYPE_MAP.put("mp2", "audio/mpeg");
		_MIME_TYPE_MAP.put("mp3", "audio/mpeg");
		_MIME_TYPE_MAP.put("aif", "audio/x-aiff");
		_MIME_TYPE_MAP.put("aiff", "audio/x-aiff");
		_MIME_TYPE_MAP.put("aifc", "audio/x-aiff");
		_MIME_TYPE_MAP.put("m3u", "audio/x-mpegurl");
		_MIME_TYPE_MAP.put("ram", "audio/x-pn-realaudio");
		_MIME_TYPE_MAP.put("rm", "audio/x-pn-realaudio");
		_MIME_TYPE_MAP.put("rpm", "audio/x-pn-realaudio-plugin");
		_MIME_TYPE_MAP.put("ra", "audio/x-realaudio");
		_MIME_TYPE_MAP.put("wav", "audio/x-wav");
		_MIME_TYPE_MAP.put("pdb", "chemical/x-pdb");
		_MIME_TYPE_MAP.put("xyz", "chemical/x-xyz");
		_MIME_TYPE_MAP.put("bmp", "image/bmp");
		_MIME_TYPE_MAP.put("gif", "image/gif");
		_MIME_TYPE_MAP.put("ief", "image/ief");
		_MIME_TYPE_MAP.put("jpeg", "image/jpeg");
		_MIME_TYPE_MAP.put("jpg", "image/jpeg");
		_MIME_TYPE_MAP.put("jpe", "image/jpeg");
		_MIME_TYPE_MAP.put("png", "image/png");
		_MIME_TYPE_MAP.put("tiff", "image/tiff");
		_MIME_TYPE_MAP.put("tif", "image/tiff");
		_MIME_TYPE_MAP.put("djvu", "image/vnd.djvu");
		_MIME_TYPE_MAP.put("djv", "image/vnd.djvu");
		_MIME_TYPE_MAP.put("wbmp", "image/vnd.wap.wbmp");
		_MIME_TYPE_MAP.put("ras", "image/x-cmu-raster");
		_MIME_TYPE_MAP.put("pnm", "image/x-portable-anymap");
		_MIME_TYPE_MAP.put("pbm", "image/x-portable-bitmap");
		_MIME_TYPE_MAP.put("pgm", "image/x-portable-graymap");
		_MIME_TYPE_MAP.put("ppm", "image/x-portable-pixmap");
		_MIME_TYPE_MAP.put("rgb", "image/x-rgb");
		_MIME_TYPE_MAP.put("xbm", "image/x-xbitmap");
		_MIME_TYPE_MAP.put("xpm", "image/x-xpixmap");
		_MIME_TYPE_MAP.put("xwd", "image/x-xwindowdump");
		_MIME_TYPE_MAP.put("igs", "model/iges");
		_MIME_TYPE_MAP.put("iges", "model/iges");
		_MIME_TYPE_MAP.put("msh", "model/mesh");
		_MIME_TYPE_MAP.put("mesh", "model/mesh");
		_MIME_TYPE_MAP.put("silo", "model/mesh");
		_MIME_TYPE_MAP.put("wrl", "model/vrml");
		_MIME_TYPE_MAP.put("vrml", "model/vrml");
		_MIME_TYPE_MAP.put("css", "text/css");
		_MIME_TYPE_MAP.put("html", "text/html");
		_MIME_TYPE_MAP.put("htm", "text/html");
		_MIME_TYPE_MAP.put("asc", "text/plain");
		_MIME_TYPE_MAP.put("txt", "text/plain");
		_MIME_TYPE_MAP.put("rtx", "text/richtext");
		_MIME_TYPE_MAP.put("rtf", "text/rtf");
		_MIME_TYPE_MAP.put("sgml", "text/sgml");
		_MIME_TYPE_MAP.put("sgm", "text/sgml");
		_MIME_TYPE_MAP.put("tsv", "text/tab-separated-values");
		_MIME_TYPE_MAP.put("wml", "text/vnd.wap.wml");
		_MIME_TYPE_MAP.put("wmls", "text/vnd.wap.wmlscript");
		_MIME_TYPE_MAP.put("etx", "text/x-setext");
		_MIME_TYPE_MAP.put("xsl", "text/xml");
		_MIME_TYPE_MAP.put("xml", "text/xml");
		_MIME_TYPE_MAP.put("mpeg", "video/mpeg");
		_MIME_TYPE_MAP.put("mpg", "video/mpeg");
		_MIME_TYPE_MAP.put("mpe", "video/mpeg");
		_MIME_TYPE_MAP.put("qt", "video/quicktime");
		_MIME_TYPE_MAP.put("mov", "video/quicktime");
		_MIME_TYPE_MAP.put("mxu", "video/vnd.mpegurl");
		_MIME_TYPE_MAP.put("avi", "video/x-msvideo");
		_MIME_TYPE_MAP.put("movie", "video/x-sgi-movie");
		_MIME_TYPE_MAP.put("ice", "x-conference/x-cooltalk");
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) {
		String pkid = request.getParameter("pkid");
		try {
		String filePath = "d:/upload/test.doc";
		String fileType = "doc";
		String fileDescription = "test";
		setResponseContentType(response, fileType, fileDescription);
		OutputStream out = response.getOutputStream();
		java.io.BufferedOutputStream bout = new java.io.BufferedOutputStream(out);
		InputStream in = new FileInputStream(new File(fileid));
		java.io.BufferedInputStream bin = new java.io.BufferedInputStream(in);
		while (bin.available() > 0) {
			byte[] b = new byte[512];
			int nResult = bin.read(b);
			if (nResult == -1)
			break;
			bout.write(b, 0, nResult);
		}
		bout.flush();
		return null;
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response){
		doGet(request,response);
	}
	private void setResponseContentType(HttpServletResponse response,
			String filetype, String description) throws Exception {
		String lowerFileType = filetype.toLowerCase();
		String contentType = (String) _MIME_TYPE_MAP.get(lowerFileType);
		if (null == contentType)
			contentType = "other/other";
		//not image file
		if (!contentType.startsWith("image")
				&& "application/octet-stream".equals(contentType)) {
			response.setHeader("Content-Type", contentType);
			response.setHeader("Content-Disposition", "attachment; filename=\""
					+ java.net.URLEncoder.encode(description + "." + filetype,
							"GBK") + "\"");
		} else {
			//image file
			response.setContentType(contentType + ";charset=GBK");
		}
	}
}</pre>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/67604#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 03 Apr 2007 13:57:43 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/67604</link>
        <guid>http://jamesby.javaeye.com/blog/67604</guid>
      </item>
      <item>
        <title>Struts2 入门实例代码</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/65208" style="color:red;">http://jamesby.javaeye.com/blog/65208</a>&nbsp;
          发表时间: 2007年03月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>Struts.xml 文件</strong><br /><br /><pre name="code" class="java">&lt;?xml version="1.0" encoding="UTF-8" ?>
&lt;!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
&lt;struts>
    &lt;constant name="struts.enable.DynamicMethodInvocation" value="true" />
    &lt;constant name="struts.devMode" value="true" />
    &lt;include file="helloworld.xml"/>
&lt;/struts></pre><br /><br /><strong>HelloWorld.xml</strong><br /><br /><pre name="code" class="java">&lt;?xml version="1.0" encoding="UTF-8" ?>
&lt;!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
&lt;struts>
	&lt;include file="struts-default.xml"/>
    &lt;package name="helloworld" namespace="/" extends="struts-default">
        &lt;interceptors>
            &lt;interceptor name ="authentication" class ="com.jamesby.struts2.LogonInterceptor"/> 
	        &lt;interceptor-stack name="helloWorldStack">
	            &lt;interceptor-ref name="authentication"/>
	            &lt;interceptor-ref name="paramsPrepareParamsStack"/>
	        &lt;/interceptor-stack>
        &lt;/interceptors>  
		&lt;default-interceptor-ref name="helloWorldStack"/>
		&lt;global-results>
			&lt;result name="login">/WEB-INF/jsp/Logon.jsp&lt;/result>				
                  &lt;/global-results>		
		&lt;action name="Logon_*" method="{1}" class="com.jamesby.struts2.Logon">
			&lt;interceptor-ref name="paramsPrepareParamsStack"/>		
			&lt;result type="redirect-action">Main&lt;/result>
			&lt;result name="input">/WEB-INF/jsp/Logon.jsp&lt;/result>		
		&lt;/action>
		&lt;action name="crud" method="{1}" class="com.jamesby.struts2.UserAction">
			&lt;result name="list">/WEB-INF/jsp/userList.jsp&lt;/result>				&lt;result name="success" type="redirect-action">crud!list&lt;/result>
			&lt;result name="input">/WEB-INF/jsp/userForm.jsp&lt;/result>
		&lt;/action>
		&lt;action name="*" class="com.jamesby.struts2.ExampleSupport">
			&lt;result>/WEB-INF/jsp/{1}.jsp&lt;/result>
		&lt;/action>         
    &lt;/package>
&lt;/struts></pre><br /><br /><strong>LogonInterceptor.java</strong><br /><br /><pre name="code" class="java">package com.jamesby.struts2;
import java.util.Map;
import com.jamesby.struts2.persist.User;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class LogonInterceptor extends AbstractInterceptor{
	@Override
	public String intercept(ActionInvocation ai) throws Exception {
		Map session = ai.getInvocationContext().getSession();
		User user = (User) session.get("user");
		if (null != user) {
			return ai.invoke();
		} else {
			return Action.LOGIN;
		}
	}
}</pre><br /><br /><strong>Logon.java</strong><br /><br /><pre name="code" class="java">package com.jamesby.struts2;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.interceptor.validation.SkipValidation;
import com.jamesby.struts2.persist.DataBaseMock;
import com.jamesby.struts2.persist.User;
import com.opensymphony.xwork2.ActionSupport;
public class Logon extends ActionSupport implements SessionAware {
	private Map session;
	public void setSession(Map session) {
		this.session = session;
	}
	@SkipValidation
	public String doInput() throws Exception {
		return INPUT;
	}
	public String doLogon() throws Exception {
		User user = DataBaseMock.selectUserByUsernameAndPassword(getUsername(),
				getPassword());
		if (null == user)
			return INPUT;
		session.put("user", user);
		return SUCCESS;
	}
	private String username;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	private String password;
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
}</pre><br /><br /><strong>UserAction.java</strong><br /><br /><pre name="code" class="java">package com.jamesby.struts2;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.struts2.interceptor.validation.SkipValidation;
import com.jamesby.struts2.persist.DataBaseMock;
import com.jamesby.struts2.persist.User;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction  extends ActionSupport {
	private User user=new User();
	private List&lt;User> userList;
	public List&lt;HashMap> getSexArray() {
		List&lt;HashMap> sexArray = new ArrayList&lt;HashMap>();
		HashMap male = new HashMap();
		male.put("key",new Integer(1));
		male.put("value","男");
		HashMap female = new HashMap();
		female.put("key",new Integer(2));
		female.put("value","女");		
		sexArray.add(male);
		sexArray.add(female);
		return sexArray;
	}	
	public List&lt;HashMap> getFromArray() {
		List&lt;HashMap> fromArray = new ArrayList&lt;HashMap>();
		HashMap bj = new HashMap();
		bj.put("id",new Integer(1));
		bj.put("name","北京");
		HashMap sh = new HashMap();
		sh.put("id",new Integer(2));
		sh.put("name","上海");		
		HashMap tj = new HashMap();
		tj.put("id",new Integer(3));
		tj.put("name","天津");
		fromArray.add(bj);
		fromArray.add(sh);
		fromArray.add(tj);
		return fromArray;
	}
	@SkipValidation
	public String doList() throws Exception {
		userList = DataBaseMock.selectAllUser();
		return "list";
	}
	@SkipValidation
	public String doInput() {
		return INPUT;
	}	
	public String doSave() {
		if (null == user.getUserid()) {
			user.setUserid(new Integer(DataBaseMock.getNewUserId()));
			DataBaseMock.saveUser(user);
		}else
		{
			DataBaseMock.updateUser(user);
		}
		return SUCCESS;
	}
	@SkipValidation
	public String doRead()
	{
		user = DataBaseMock.getUser(user.getUserid());
		return INPUT;
	}
	@SkipValidation
	public String doDelete() {
		DataBaseMock.deleteUser(user);
		return SUCCESS;
	}		
	public List&lt;User> getUserList() {
		return userList;
	}
	public void setUserList(List&lt;User> userList) {
		this.userList = userList;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
}</pre><br /><br /><strong>ExampleSupport.java</strong><br /><br /><pre name="code" class="java">package com.jamesby.struts2;
import com.opensymphony.xwork2.ActionSupport;
public class ExampleSupport extends ActionSupport {
}</pre><br /><br /><strong>User.java</strong><br /><br /><pre name="code" class="java">package com.jamesby.struts2.persist;
public class User {
	private Integer userid;
	private String username;
	private String password;
	private int sex;
	private int age;
	private int from;
	public int getFrom() {
		return from;
	}
	public void setFrom(int from) {
		this.from = from;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public int getSex() {
		return sex;
	}
	public void setSex(int sex) {
		this.sex = sex;
	}
	public Integer getUserid() {
		return userid;
	}
	public void setUserid(Integer userid) {
		this.userid = userid;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}</pre><br /><br /><strong>DataBaseMock.java</strong><br /><br /><pre name="code" class="java">package com.jamesby.struts2.persist;
import java.util.ArrayList;
import java.util.List;
public class DataBaseMock {
	private static List&lt;User> _cache = new ArrayList&lt;User>();
	private static int userid = 0;
	static {
		User user = new User();
		user.setUserid(new Integer(0));
		user.setUsername("admin");
		user.setPassword("12345688");
		user.setFrom(1);// 北京
		user.setSex(1);// 男
		user.setAge(18);
		_cache.add(user);
	}
	public static User selectUserByUsernameAndPassword(String username,String password)
	{
		for (User u : _cache) {
			if (u.getUsername().equals(username)&&u.getPassword().equals(password)) {
				return u;
			}
		}
		return null;
	}
	public static List&lt;User> selectAllUser()
	{
		return _cache;
	}
	public static int getNewUserId() {
		return ++userid;
	}
	public static void saveUser(User user) {
		_cache.add(user);
	}
	public static void updateUser(User user) {
		deleteUser(user);
		saveUser(user);
	}
	public static void deleteUser(User user) {
		for (User u : _cache) {
			if (u.getUserid().intValue() == user.getUserid().intValue()) {
				_cache.remove(u);
				break;
			}
		}
	}
	public static User getUser(Integer userid) {
		return _cache.get(userid);
	}
}</pre><br /><br /><strong>Logon-validation.xml</strong><br /><br /><pre name="code" class="java">&lt;!DOCTYPE validators PUBLIC 
"-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
&lt;validators>
    &lt;field name="username">
        &lt;field-validator type="requiredstring">
			&lt;message key="requiredstring"/>
        &lt;/field-validator>
    &lt;/field>
    &lt;field name="password">
        &lt;field-validator type="requiredstring">
			&lt;message key="requiredstring"/>
        &lt;/field-validator>
    &lt;/field>
&lt;/validators></pre><br /><br /><strong>UserAction-validation.xml</strong><br /><br /><pre name="code" class="java">&lt;!DOCTYPE validators PUBLIC 
"-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
&lt;validators>
  &lt;field name="user.username">
     &lt;field-validator type="requiredstring">
        &lt;message key="errors.required.username"/>
      &lt;/field-validator>
  &lt;/field>
  &lt;field name="user.password">
     &lt;field-validator type="requiredstring">
        &lt;message key="errors.required.password"/>
      &lt;/field-validator>
  &lt;/field>
  &lt;field name="user.sex">
     &lt;field-validator type="required">
        &lt;message key="errors.required.sex"/>
      &lt;/field-validator>
  &lt;/field>  
  &lt;field name="user.age">
     &lt;field-validator type="required" short-circuit="true">
        &lt;message key="errors.required.age"/>
      &lt;/field-validator>
      &lt;field-validator type="int">
      	&lt;param name="min">18&lt;/param>
      	&lt;param name="max">65&lt;/param>
        &lt;message key="errors.required.age.limit"/>
      &lt;/field-validator>
  &lt;/field>
  &lt;field name="user.from">
     &lt;field-validator type="required">
        &lt;message key="errors.required.from"/>
      &lt;/field-validator>
  &lt;/field>    
&lt;/validators></pre><br /><br /><strong>package.properties</strong><br /><br /><pre name="code" class="java">requiredstring = $\{getText(fieldName)} is required.
password = Password
username = User Name
main.message = This is main page...................
label.userList= All User List

user.username=Username
user.password=Password
user.sex=Sex
user.age=Age
user.from=From

errors.required.username=Username is required
errors.required.password=Password is required
errors.required.sex=Sex is Required
errors.required.from=From is Required
errors.required.age.limit=Age between 18 and 65
errors.required.age.limit=Age between 18 and 65</pre><br /><br /><strong>Logon.jsp</strong><br /><br /><pre name="code" class="java">&lt;%@ taglib prefix="s" uri="/struts-tags" %>
&lt;html>
&lt;head>
  &lt;title>Logon&lt;/title>
&lt;/head>
&lt;body>
&lt;s:form action="Logon!logon"> 
  &lt;s:textfield label="%{getText('username')}" name="username"/>
  &lt;s:password label="%{getText('password')}" name="password" />
  &lt;s:submit/>
&lt;/s:form>
&lt;/body>
&lt;/html></pre><br /><br /><strong>userList.jsp</strong><br /><br /><pre name="code" class="java">&lt;%@ page contentType="text/html;charset=GBK"%>
&lt;%@taglib prefix="s" uri="/struts-tags" %>

&lt;head>
    &lt;title>&lt;s:text name="label.userList"/>&lt;/title>
&lt;/head>

&lt;s:url id="url" action="crud!input" />
&lt;a href="&lt;s:property value="#url"/>">Add New User&lt;/a>
&lt;br>
&lt;table border="1">
	&lt;tr class="&lt;s:if test="#status.even">even&lt;/s:if>&lt;s:else>odd&lt;/s:else>">
		&lt;td>用户ID&lt;/td>
		&lt;td>用户名&lt;/td>
		&lt;td>性别&lt;/td>
		&lt;td>年龄&lt;/td>
		&lt;td>来自&lt;/td>
		&lt;td>修改&lt;/td>
		&lt;td>删除&lt;/td>
	&lt;/tr>	
&lt;s:iterator value="userList" status="status">
	&lt;tr class="&lt;s:if test="#status.even">even&lt;/s:if>&lt;s:else>odd&lt;/s:else>">
		&lt;td>&lt;s:property value="userid" />&lt;/td>
		&lt;td>&lt;s:property value="username" />&lt;/td>
		&lt;td>
			&lt;s:if test="sex==1">男&lt;/s:if>
			&lt;s:else>女&lt;/s:else>
		&lt;/td>
		&lt;td>&lt;s:property value="age" />&lt;/td>
		&lt;td>
			&lt;s:if test="from==1">北京&lt;/s:if>
			&lt;s:if test="from==2">上海&lt;/s:if>
			&lt;s:if test="from==3">天津&lt;/s:if>
		&lt;/td>
		&lt;td>
			&lt;a href="crud!read.action?user.userid=&lt;s:property value="userid" />">修改&lt;/a>
		&lt;/td>
		&lt;td>
			&lt;a href="crud!delete.action?user.userid=&lt;s:property value="userid" />">删除&lt;/a>
		&lt;/td>
	&lt;/tr>	
&lt;/s:iterator>
&lt;/table></pre><br /><br /><br /><strong>userForm.jsp</strong><br /><br /><pre name="code" class="java">&lt;%@ page contentType="text/html;charset=GBK"%>
&lt;%@taglib prefix="s" uri="/struts-tags" %>
User Form
&lt;s:form action="crud!save.action" method="post">
    &lt;s:textfield required="true" name="user.username" value="%{user.username}" label="%{getText('user.username')}" size="40"/>
    &lt;s:textfield required="true" name="user.password" value="%{user.password}" label="%{getText('user.password')}" size="40"/>
    &lt;s:radio required="true" name="user.sex" listKey="key" listValue="value" value="%{user.sex}" label="%{getText('user.sex')}" list="sexArray"/>
    &lt;s:textfield required="true" name="user.age" value="%{user.age}" label="%{getText('user.age')}" size="40"/>
    &lt;s:select label="%{getText('user.from')}" name="user.from" headerKey="" headerValue="Select From" list="fromArray" listKey="id" listValue="name" value="user.from" required="true"/>
    &lt;s:hidden name="user.userid" value="%{user.userid}"/>
    &lt;s:submit value="Submit"/>
    &lt;s:submit value="Cancel" name="redirect-action:crud!list"/>
&lt;/s:form></pre><br /><br /><strong>应用程序目录结构</strong><br /><br /><pre name="code" class="java">WEB-INF
│  web.xml
│
├─classes
│  │  commons-logging.properties
│  │  helloworld.xml
│  │  log4j.properties
│  │  struts.properties
│  │  struts.xml
│  │
│  └─com
│      └─jamesby
│          └─struts2
│              │  ExampleSupport.class
│              │  Logon-validation.xml
│              │  Logon.class
│              │  LogonInterceptor.class
│              │  package.properties
│              │  UserAction-validation.xml
│              │  UserAction.class
│              │
│              └─persist
│                      DataBaseMock.class
│                      User.class
│
├─jsp
│      Logon.jsp
│      Main.jsp
│      userForm.jsp
│      userList.jsp
│
├─lib
       commons-collections-3.1.jar
       commons-logging-1.0.4.jar
       freemarker-2.3.8.jar
       log4j-1.2.9.jar
       ognl-2.6.11.jar
       struts2-core-2.0.6.jar
       xwork-2.0.1.jar
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/65208#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 24 Mar 2007 12:33:46 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/65208</link>
        <guid>http://jamesby.javaeye.com/blog/65208</guid>
      </item>
      <item>
        <title>软件设计应遵循的原则</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/60873" style="color:red;">http://jamesby.javaeye.com/blog/60873</a>&nbsp;
          发表时间: 2007年03月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>转自</strong><br />http://aladdin.javaeye.com/blog/40809<br />http://blog.csdn.net/ponent2005/archive/2005/07/18/428305.aspx<br /><br /><strong>一、单一职责原则(SRP)</strong><br /><br />就一个类而言,应该仅有一个引起它变化的原因,如果你能想到多于一个的动机去改变一个类,那么这个类就具有多于一个的指责.应该把多于的指责分离出去,分别再创建一些类来完成每一个指责.<br /><br /><strong>二、开闭原则(OCP)</strong><br /><br /> 钻研OO设计模式有一段时间了，可是天生愚笨，总是不得真谛，于是想是不是该跳出来仔细的想一想了呢？为什么需要设计模式？GoF的23设计模式的设计原则是什么呢？在查阅了一些资料后，仿佛有了一些感觉，其实设计模式的原则就是OOD的原则，或者说设计模式是为了达到OOD的远景而提出的，所以正真的想掌握OO的精髓，那么学习设计模式是最好的途径，而想真正掌握设计模式的精髓，那麽就必须好好的理解一下OOD的设计原则，这篇文章关注的只是其中的一个原则--OCP。下面通过引用CSDN上Health King的专栏的一篇我认为比较好的关于OCP原则的文章开始我们的认识OCP之旅吧！<br /><br />     原文链接：http://blog.csdn.net/kxy/archive/2005/06/27/405013.aspx<br /><br />     在继续《设计模式精解》这本书之前，我们来学习些OOD的一些设计原则。这些原则在提高一个系统可维护性的同时，提高这个系统的可复用性他们是一些指导原则，依照这些原则设计，我们就可以有效的提高系统的复用性，同时提高系统的可维护性。<br /><br />     这些OOD原则的一个基石就是“开-闭原则”(Open-Closed Principle OCP)。这个原则最早是由Bertrand Meyer提出,英文的原文是:Software entities should be open for extension，but closed for modification。意思是说,一个软件实体应当对扩展开放，对修改关闭。也就是说，我们在设计一个模块的时候，应当使这个模块可以在不被修改的前提下被扩展，换句话说就是，应当可以在不必修改源代码的情况下改变这个模块的行为。<br /><br />     满足OCP的设计给系统带来两个无可比拟的优越性：<br />     通过扩展已有的软件系统，可以提供新的行为以满足对软件的新需求，使变化中的软件系统有一定的适应性和灵活性。<br />     已有的软件模块，特别是最重要的抽象层模块不能再修改，这就使变化中的软件系统有一定的稳定性和延续性。<br /><br />     具有这两个优点的软件系统是一个高层次上实现了复用的系统，也是一个易于维护的系统。那么，我们如何才能做到这个原则呢？不能修改而可以扩展，这个看起来是自相矛盾的。其实这个是可以做到的，按面向对象的说法，这个就是不允许更改系统的抽象层，而允许扩展的是系统的实现层。<br /><br />解决问题的关键在：抽象化。我们让模块依赖于一个固定的抽象体，这样它就是不可以修改的；同时，通过这个抽象体派生，我们就可以扩展此模块的行为功能。如此，这样设计的程序只通过增加代码来变化而不是通过更改现有代码来变化，前面提到的修改的副作用就没有了。<br /><br />   “开-闭”原则如果从另外一个角度讲述，就是所谓的“对可变性封装原则”(Principle of Encapsulation of Variation, EVP)。讲的是找到一个系统的可变因素，将之封装起来。在我们考虑一个系统的时候，我们不要把关注的焦点放在什么会导致设计发生变化上，而是考虑允许什么发生变化而不让这一变化导致重新设计。也就是说，我们要积极的面对变化，积极的包容变化，而不是逃避。<br /><br />     [SHALL01]将这一思想用一句话总结为：“找到一个系统的可变因素，将它封装起来”，并将它命名为“对可变性的封装原则”。<br /><br />    “对可变性的封装原则”意味者两点：<br />     一种可变性应当被封装到一个对象里面，而不应当散落到代码的很多角落里面。同一种可变性的不同表象意味着同一个继承等级结构中的 具体子类。继承应当被看做是封装变化的方法，而不应当是被认为从一般的对象生成特殊的对象的方法(继承经常被滥用)。<br />     一种可变性不应当与另外一种可变性混合在一起。从具体的类图来看，如果继承结构超过了两层，那么就意味着将两种不同的可变性混合在了一起。<br /><br />    “对可变性的封装原则”从工程的角度说明了如何实现OCP。如果按照这个原则来设计，那么系统就应当是遵守OCP的。但是现实往往是残酷的，我们不可能100%的遵守OCP，但是我们要向这个目标来靠近。设计者要对设计的模块对何种变化封闭做出选择。<br /><br />     好了，上面就是引用的全文了。那麽在实际设计和开发之中，我们该如何重构我们的设计和代码呢？<br />     答案是：抽象(Astraction)、多态(Polymorphism)、继承(Inheritance)、接口(Interface)。利用这些就可以让我们去实践OCP了，这样就会让我们的设计符合OCP，符合该法则便意味着最高等级的复用性(Reusability)和可维护性(Maintainability)。当然我们也有很多的设计模式可以利用来很优美的解决如何封装变化等问题，但是不要忘了，设计模式的基础也是抽象(Astraction)、多态(Polymorphism)、继承(Inheritance)、接口(Interface)啊。还是从最简单开始吧，千里之行，始于足下...<br /><br />     考虑下面某个类的方法：但是现在每当计价策略发生改变，我们就必须修改Part 的每个子类！<br />     一个更好的思路是采用一个PricePolicy类，通过对其进行继承以提供不同的计价策略，那麽这里就是在运用设计模式里面的策略模式了，解决起来算是很完美了：     看起来我们所做的就是将问题推迟到另一个类中，将“变化”封装在PricePolicy类里面。但是使用该解决方案，我们可通过改变Part对象，在运行期间动态地来设定计价的策略。另一个解决方案是使每个ConcretePart从数据库或属性文件中获取其当前的价格，这样相当于把“变化”封装在了属性文件里面了。<br /><pre name="code" class="java">public double totalPrice(Part[] parts) {    
      double total = 0.0;    
      for(int i = 0;i 
            total += parts[i].getPrice();    
    }    
      return total;    
}   </pre> <br />  以上函数的工作是在制订的部件数组中计算各个部件价格的总和。若Part是一个基类或接口且使用了多态，则该类可很容易地来适应新类型的部件，而不必对其进行修改。其将符合OCP<br /><br />     但是在计算总价格时，若财务部颁布主板和内存应使用额外费用，则将如何去做。下列的代码是如何来做的呢？这符合OCP吗？<br /><pre name="code" class="java">public double totalPrice(Part[] parts) {    
      double total = 0.0;    
      for(int i = 0;i 
            if(parts[i] instanceof Motherboard)    
                total += (1.45*parts[i].getPrice());    
            else if(parts[i] instanceof Memory)    
                total += (1.27*parts[i].getPrice());    
            else     
                total += parts[i].getPrice();    
      }    
      return total;    
} </pre>   <br />  当每次财务部提出新的计价策略，我们都不得不要修改totalPrice()方法！这并非“对更改是封闭的”。显然，策略的变更便意味着我们不得不要在一些地方修改代码的，因此不符合OCP，那麽我们该如何去做呢？<br /><br />    为了使用我们第一个版本的totalPrice()，我们可以将计价策略合并到Part的getPrice()方法中。<br />    这里是Part和ConcretePart类的示例：<br /><pre name="code" class="java">public class Part {    
       private double basePrice;    
       public void setPrice(double price) {    
           basePrice = price;    
       }    
       public double getPrice() {    
           return basePrice;    
       }    
}    
public class Motherboard extends Part {    
       public double getPrice() {    
           return 1.45*basePrice;    
       }    
}    
public class Memory extends Part {    
       public double getPrice() {    
           return 1.27*basePrice;    
       }    
}  </pre>  <br />   <br />    但是现在每当计价策略发生改变，我们就必须修改Part 的每个子类！<br />       一个更好的思路是采用一个PricePolicy类，通过对其进行继承以提供不同的计价策略，那麽这里就是在运用设计模式里面的策略模式了，解决起来算是很完美了：<br /><pre name="code" class="java">public class Part {    
       private PricePolicy pricePolicy;    
       public void setPricePolicy(PricePolicy policy) {    
           pricePolicy = policy;    
       }    
       public void setPrice(double price) {    
           pricePolicy.setPrice(price);    
       }    
       public double getPrice() {    
           return pricePolicy.getPrice();    
       }    
}    
public class PricePolicy {    
       private double basePrice;    
       public void setPrice(double price) {    
           basePrice = price;    
       }    
       public double getPrice() {    
           return basePrice;    
       }    
}       
public class SalePrice extends PricePolicy {    
       private double discount;    
       public void setDiscount(double discount) {    
           this.discount = discount;    
       }    
       public double getPrice() {    
           return basePrice*discount;    
       }       
}       </pre>     <br /><br />看起来我们所做的就是将问题推迟到另一个类中，将“变化”封装在PricePolicy类里面。但是使用该解决方案，我们可通过改变Part对象，在运行期间动态地来设定计价的策略。另一个解决方案是使每个ConcretePart从数据库或属性文件中获取其当前的价格，这样相当于把“变化”封装在了属性文件里面了。<br /><br /><br /><strong>三、里氏代换原则(LSP)</strong><br /><br />(1) 由Barbar Liskov(芭芭拉.里氏)提出，是继承复用的基石。<br />(2) 严格表达:如果每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换称o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型.<br />    换言之,一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且它根本不能察觉出基类对象和子类对象的区别.只有衍生类可以替换基类，软件单位的功能才能不受影响，基类才能真正被复用，而衍生类也能够在基类的基础上增加新功能。<br />(3) 反过来的代换不成立<br />(4) &lt;墨子.小取>中说:"白马,马也; 乘白马,乘马也.骊马(黑马),马也;乘骊马,乘马也."<br />(5) 该类西方著名的例程为:正方形是否是长方形的子类(答案是"否")。类似的还有椭圆和圆的关系。<br />(6) 应当尽量从抽象类继承,而不从具体类继承,一般而言,如果有两个具体类A,B有继承关系,那么一个最简单的修改方案是建立一个抽象类C,然后让类A和B成为抽象类C的子类.即如果有一个由继承关系形成的登记结构的话,那么在等级结构的树形图上面所有的树叶节点都应当是具体类;而所有的树枝节点都应当是抽象类或者接口.<br />(7) "基于契约设计(Design By Constract),简称DBC"这项技术对LISKOV代换原则提供了支持.该项技术Bertrand Meyer伯特兰做过详细的介绍:<br />使用DBC,类的编写者显式地规定针对该类的契约.客户代码的编写者可以通过该契约获悉可以依赖的行为方式.契约是通过每个方法声明的前置条件(preconditions)和后置条件(postconditions)来指定的.要使一个方法得以执行,前置条件必须为真.执行完毕后,该方法要保证后置条件为真.就是说,在重新声明派生类中的例程(routine)时,只能使用相等或者更弱的前置条件来替换原始的前置条件,只能使用相等或者更强的后置条件来替换原始的后置条件.<br /><br />    一个软件实体如果使用的是一个基类的话那么一定适用于其子类，而且它察觉不出基类对象和子类对象的区别。也就是说，在软件里面，把基类都替换成它的子类，程序的行为没有变化。<br /><br /> LSP是继承复用的基石，只有当衍生类可以替换掉基类，软件单位的功能不受到影响时，基类才能真正被复用，而衍生类也能够在基类的基础上增加新的行为。<br />    <br />下面，我们从代码重构的角度来对LSP进行理解。LSP讲的是基类和子类的关系。只有当这种关系存在时，里氏代换关系才存在。如果两个具体的类A，B之间的关系违反了LSP的设计，(假设是从B到A的继承关系)那么根据具体的情况可以在下面的两种重构方案中选择一种。<br />     <br />创建一个新的抽象类C，作为两个具体类的超类，将A，B的共同行为移动到C中来解决问题。<br />     从B到A的继承关系改为委派关系。<br />     为了说明，我们先用第一种方法来看一个例子，第二种办法在另外一个原则中说明。我们就看那个著名的长方形和正方形的例子。对于长方形的类，如果它的长宽相等，那么它就是一个正方形，因此，长方形类的对象中有一些正方形的对象。对于一个正方形的类，它的方法有个setSide和getSide，它不是长方形的子类，和长方形也不会符合LSP。<br /><br />那么，如果让正方形当做是长方形的子类，会出现什么情况呢？我们让正方形从长方形继承，然后在它的内部设置width等于height，这样，只要width或者height被赋值，那么width和height会被同时赋值，这样就保证了正方形类中，width和height总是相等的.现在我们假设有个客户类，其中有个方法，规则是这样的，测试传入的长方形的宽度是否大于高度，如果满足就停止下来，否则就增加宽度的值。现在我们来看，如果传入的是基类长方形，这个运行的很好。根据LSP，我们把基类替换成它的子类，结果应该也是一样的，但是因为正方形类的width和height会同时赋值，这个方法没有结束的时候，条件总是不满足，也就是说，替换成子类后，程序的行为发生了变化，它不满足LSP。<br /><br />那么我们用第一种方案进行重构，我们构造一个抽象的四边形类，把长方形和正方形共同的行为放到这个四边形类里面，让长方形和正方形都是它的子类，问题就OK了。对于长方形和正方形，取width和height是它们共同的行为，但是给width和height赋值，两者行为不同，因此，这个抽象的四边形的类只有取值方法，没有赋值方法。上面的例子中那个方法只会适用于不同的子类，LSP也就不会被破坏。<br /><br />在进行设计的时候，我们尽量从抽象类继承，而不是从具体类继承。如果从继承等级树来看，所有叶子节点应当是具体类，而所有的树枝节点应当是抽象类或者接口。当然这个只是一个一般性的指导原则，使用的时候还要具体情况具体分析。<br /><br /><strong>四、依赖倒致原则(DIP)</strong><br /><br />要求客户端依赖于抽象耦合.<br />(1) 表述:抽象不应当依赖于细节,细节应当依赖于抽象.(Program to an interface, not an implementaction)<br /><br />(2) 表述二:针对接口编程的意思是说,应当使用接口和抽象类进行变量的类型声明,参量的类型声明,方法的返还类型声明,以及数据类型的转换等.不要针对实现编程的意思就是说,不应当使用具体类进行变量的类型声明,参量类型声明,方法的返还类型声明,以及数据类型的转换等.<br />   要保证做到这一点,一个具体的类应等只实现接口和抽象类中声明过的方法,而不应当给出多余的方法.<br />   只要一个被引用的对象存在抽象类型,就应当在任何引用此对象的地方使用抽象类型,包括参量的类型声明,方法返还类型的声明,属性变量的类型声明等.<br /><br />(3) 接口与抽象的区别就在于抽象类可以提供某些方法的部分实现,而接口则不可以,这也大概是抽象类唯一的优点.如果向一个抽象类加入一个新的具体方法,那么所有的子类型一下子就都得到得到了这个新的具体方法,而接口做不到这一点.如果向一个接口加入了一个新的方法的话,所有实现这个接口的类就全部不能通过编译了,因为它们都没有实现这个新声明的方法.这显然是接口的一个缺点.<br /><br />(4) 一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的登记结构中,而由于一般语言都限制一个类只能从最多一个超类继承,因此将抽象作为类型定义工具的效能大打折扣.<br />   反过来,看接口,就会发现任何一个实现了一个接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个接口.<br /><br />(5) 从代码重构的角度上讲,将一个单独的具体类重构成一个接口的实现是很容易的,只需要声明一个接口,并将重要的方法添加到接口声明中,然后在具体类定义语句中加上保留字以继承于该接口就行了.<br />   而作为一个已有的具体类添加一个抽象类作为抽象类型不那么容易,因为这个具体类有可能已经有一个超类.这样一来,这个新定义的抽象类只好继续向上移动,变成这个超类的超类,如此循环,最后这个新的抽象类必定处于整个类型等级结构的最上端,从而使登记结构中的所有成员都会受到影响.<br /><br />(6) 接口是定义混合类型的理想工具,所为混合类型,就是在一个类的主类型之外的次要类型.一个混合类型表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为.<br /><br />(7) 联合使用接口和抽象类:<br />   由于抽象类具有提供缺省实现的优点,而接口具有其他所有优点,所以联合使用两者就是一个很好的选择.<br />   首先,声明类型的工作仍然接口承担的,但是同时给出的还有一个抽象类,为这个接口给出一个缺省实现.其他同属于这个抽象类型的具体类可以选择实现这个接口,也可以选择继承自这个抽象类.如果一个具体类直接实现这个接口的话,它就必须自行实现所有的接口;相反,如果它继承自抽象类的话,它可以省去一些不必要的的方法,因为它可以从抽象类中自动得到这些方法的缺省实现;如果需要向接口加入一个新的方法的话,那么只要同时向这个抽象类加入这个方法的一个具体实现就可以了,因为所有继承自这个抽象类的子类都会从这个抽象类得到这个具体方法.这其实就是缺省适配器模式(Defaule Adapter).<br /><br />(8) 什么是高层策略呢?它是应用背后的抽象,是那些不随具体细节的改变而改变的真理. 它是系统内部的系统(隐喻).<br /><br /><br /><strong>五、接口隔离原则(ISP)</strong><br /><br />(1) 一个类对另外一个类的依赖是建立在最小的接口上。<br />(2) 使用多个专门的接口比使用单一的总接口要好.根据客户需要的不同,而为不同的客户端提供不同的服务是一种应当得到鼓励的做法.就像"看人下菜碟"一样,要看客人是谁,再提供不同档次的饭菜.<br />(3) 胖接口会导致他们的客户程序之间产生不正常的并且有害的耦合关系.当一个客户程序要求该胖接口进行一个改动时,会影响到所有其他的客户程序.因此客户程序应该仅仅依赖他们实际需要调用的方法.<br />     <br /><strong>六、合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)</strong><br /><br />在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过这些向对象的委派达到复用已有功能的目的.这个设计原则有另一个简短的表述:要尽量使用合成/聚合,尽量不要使用继承.<br /><br /><strong>七、迪米特法则(Law of Demeter LoD)</strong><br /><br />又叫做最少只是原则(Least Knowledge Principle,LKP),就是说,一个对象应当对其他对象有尽可能少的了了解.<br />迪米特法则最初是用来作为面向对象的系统设计风格的一种法则,与1987年秋天由Ian Holland在美国东北大学为一个叫做迪米特(Demeter)的项目设计提出的,因此叫做迪米特法则[LIEB89][LIEB86].这条法则实际上是很多著名系统,比如火星登陆软件系统,木星的欧罗巴卫星轨道飞船的软件系统的指导设计原则.<br />没有任何一个其他的OO设计原则象迪米特法则这样有如此之多的表述方式,如下几种:<br />(1) 只与你直接的朋友们通信(Only talk to your immediate friends)<br />(2) 不要跟"陌生人"说话(Don't talk to strangers)<br />(3) 每一个软件单位对其他的单位都只有最少的只是,而且局限于那些本单位密切相关的软件单位.<br />就是说,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/60873#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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>Mon, 19 Mar 2007 12:10:22 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/60873</link>
        <guid>http://jamesby.javaeye.com/blog/60873</guid>
      </item>
      <item>
        <title>Java 5.0 枚举</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/59274" style="color:red;">http://jamesby.javaeye.com/blog/59274</a>&nbsp;
          发表时间: 2007年03月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.ibm.com/developerworks/cn/java/j-enums.html" target="_blank">http://www.ibm.com/developerworks/cn/java/j-enums.html</a><br />http://www.ibm.com/developerworks/cn/java/j-tiger04195<br />http://dev2dev.bea.com.cn/techdoc/20060105718.html
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/59274#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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>Mon, 12 Mar 2007 15:09:43 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/59274</link>
        <guid>http://jamesby.javaeye.com/blog/59274</guid>
      </item>
      <item>
        <title>关于web-inf/classes的优先级高于web-inf/lib的优先级</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/58182" style="color:red;">http://jamesby.javaeye.com/blog/58182</a>&nbsp;
          发表时间: 2007年03月08日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>背景</strong><br /><br />一直以来都知道web-inf/classes的优先级高于web-inf/lib的优先级,但是实际却未必真的注意了.<br /><br />因为程序每天都需要更新发布,而且服务器处于托管状态,网络传输速度慢,因此更新系统的时候每次都是将配置文件和classes下面的文件进行覆盖操作.<br /><br />如上方式部署就产生了一个问题,本来我的系统里面有一些通用类,最近打包成lib方式以供其它应用使用,而且这个包不断的更新.<br /><br />将该包部署后发现我的系统总是报class的方法找不到,最后查到原因是因为我的应用的classes下面的class与包里面的class重名,因为classloader会优先加载classes下面的class所致.<br /><br /><strong>解决办法</strong><br /><br />将classes下面的对应的classes删除,根本解决办法,每次将classes下面的全部删除,然后重新拷贝,而不是简单覆盖.
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/58182#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 08 Mar 2007 12:11:35 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/58182</link>
        <guid>http://jamesby.javaeye.com/blog/58182</guid>
      </item>
      <item>
        <title>Spring MVC 的 multipartResolver 不能同iWebOffice2006 共同使用</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/57381" style="color:red;">http://jamesby.javaeye.com/blog/57381</a>&nbsp;
          发表时间: 2007年03月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          项目使用iWebOffice2006，本来可以正常使用，但是系统有文件上传需求，故定义了一个multipartResolver，后发现 iWebOffice2006 控件不能正常使用！<br /><br />解决办法有两个,一是不使用Spring 的 multipartResolver 进行文件上传，二是将iWebOffice2006 的serverurl替换成一个jsp或者servlet实现，而不用spring 的 controller来实现。
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/57381#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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>Mon, 05 Mar 2007 12:10:01 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/57381</link>
        <guid>http://jamesby.javaeye.com/blog/57381</guid>
      </item>
      <item>
        <title>XWork2.0 入门实例代码</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/57160" style="color:red;">http://jamesby.javaeye.com/blog/57160</a>&nbsp;
          发表时间: 2007年03月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>Xwork.xml 配置文件</strong><br /><br /><pre name="code" class="java">&lt;!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 2.0//EN" "http://www.opensymphony.com/xwork/xwork-2.0.dtd">
&lt;xwork>
    &lt;include file="xwork-default.xml"/>
    &lt;package name="default" extends="xwork-default" namespace="/test">
		&lt;result-types>
			&lt;result-type name="successResult" class="com.jamesby.xwork.helloworld.SuccessResult" />
			&lt;result-type name="failedResult" class="com.jamesby.xwork.helloworld.FailedResult" />
		&lt;/result-types>    
    	&lt;interceptors>
	    	&lt;interceptor name="testInterceptor"  class="com.jamesby.xwork.helloworld.TestInterceptor"/>
	    &lt;/interceptors>	
	   &lt;action name="testAction" class="com.jamesby.xwork.helloworld.TestAction">
			&lt;result name="success" type="chain">
				&lt;param name="actionName">testChainAction&lt;/param>
			&lt;/result>	
			&lt;result name="failed" type="failedResult"/>			
			&lt;interceptor-ref name="params"/>
			&lt;!--Model Driven-->
			&lt;interceptor-ref name="model-driven"/>
			&lt;interceptor-ref name="defaultStack"/>
			
			&lt;interceptor-ref name="testInterceptor"/>			
	   &lt;/action>
	   
	   &lt;action name="testChainAction" class="com.jamesby.xwork.helloworld.TestChainAction">
			&lt;result name="success" type="successResult">
				&lt;param name="param">Custom Type&lt;/param>
			&lt;/result>	

			&lt;result name="failed" type="failedResult"/>			

			&lt;interceptor-ref name="params"/>
			&lt;interceptor-ref name="model-driven"/>
			&lt;interceptor-ref name="defaultStack"/>
			&lt;interceptor-ref name="testInterceptor"/>

	   &lt;/action>	   
    &lt;/package>
    &lt;constant name="devMode" value="false" />
&lt;/xwork></pre><br /><br /><strong>xwork-conversion.properties 属性文件</strong><br /><br /><pre name="code" class="java">com.jamesby.xwork.helloworld.TestType=com.jamesby.xwork.helloworld.TestConvert</pre><br /><br /><strong>Action 文件和测试Chain的Action 文件</strong><br /><br /><pre name="code" class="java">public class TestAction implements Action, ModelDriven {
	TestModel book = new TestModel();
	int id;
	public String execute() throws Exception {

		System.out.println("\nAction is invoked............");
		System.out.println("Action:Received Id is " + id);
		System.out.println("Action:Receive Book Title is " + book.getTitle());

		// book = bookDAO.findById(id, Book.class);
		book.setTitle("Action Title");
		if (id &lt; 1000)
			return "failed";
		return "success";
	}
	public TestModel getModel() {
		return book;
	}
	public void setId(int id) {
		this.id = id;
	}
}</pre><br /><br /><pre name="code" class="java">public class TestChainAction implements Action, ModelDriven {
	TestModel book = new TestModel();
	int id;
	public String execute() throws Exception {

		System.out.println("\nChain Action is invoked............");
		System.out.println("Chain Action:Received Id is " + id);
		System.out.println("Chain Action:Receive Book Title is " + book.getTitle());

		// book = bookDAO.findById(id, Book.class);
		book.setTitle("Chain Action Title");
		if (id &lt; 2000)
			return "success";
		return "failed";
	}
	public TestModel getModel() {
		return book;
	}
	public void setId(int id) {
		this.id = id;
	}
}</pre><br /><br /><strong>ModelDriven 的模型代码</strong><br /><br /><pre name="code" class="java">public class TestModel {
	String id;
	String title;
	public void setId(String id) {
		this.id = id;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getId() {
		return this.id;
	}
	public String getTitle() {
		return this.title;
	}
}</pre><br /><br /><strong>Result代码</strong><br /><br /><pre name="code" class="java">public class SuccessResult implements Result {
		private TestType param;
		public void setParam(TestType param) {
			this.param = param;
		}
		public void execute(ActionInvocation invocation) {
			System.out.println("\nSuccessResult is invoked..............");
			System.out.println("param is "+param.getValue());
			
			System.out.println("SuccessResult:Received Title is "
					+ invocation.getStack().findValue("title"));
		}
}


public class FailedResult implements Result {
	public void execute(ActionInvocation invocation) {
		System.out.println("\nFailedResult is invoked..............");
		System.out.println("FailedResult:Received Title is "
				+ invocation.getStack().findValue("title"));

	}
}</pre><br /><br /><strong>TypeConvert 文件代码</strong><br /><br /><pre name="code" class="java">import java.lang.reflect.Member;
import java.util.Map;

import ognl.DefaultTypeConverter;

public class TestConvert extends DefaultTypeConverter {
	public Object convertValue(Map context, Object target, Member member,
			String propertyName, Object value, Class toType) {
		return new TestType("" + value);
	}
}


public class TestType {
	private String value;
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public TestType(String value) {
		this.value = value;
	}
}</pre><br /><br /><strong>自定义Interceptor 和 PreResultListener</strong><br /><br /><pre name="code" class="java">public class TestInterceptor extends AbstractInterceptor {
	public String intercept(ActionInvocation invocation) throws Exception {
		invocation.addPreResultListener(new PreResultListener() {
			public void beforeResult(ActionInvocation invocation,
					String resultCode) {
				System.out.println("\nPre Result Listerer is invoked........");
				
			}
		});
		return invocation.invoke();
	}
}</pre><br /> <br /><strong>Main应用程序代码</strong><br /><br /><pre name="code" class="java">public class HelloWorldMain {

	public static void main(String[] args) throws Exception {
		Map paramMap = new HashMap();
		/**
		 * 1000 以下 testAction Failed Result
		 * 1000-2000 testAction testChainAction SuccessResult
		 * 2000 以上 testAction testChainAction Failed Result
		 */
		paramMap.put("id", "500");
		paramMap.put("title", "param title");

		Map context = new HashMap();
		context.put(ActionContext.PARAMETERS, paramMap);

		ConfigurationManager cm = new ConfigurationManager();
		Configuration conf = cm.getConfiguration();
		Container containter = conf.getContainer();
		DefaultActionProxyFactory actionProxyFactory = new DefaultActionProxyFactory();
		actionProxyFactory.setContainer(containter);
		ActionProxy proxy = actionProxyFactory.createActionProxy("/test",
				"testAction", context);
		String result = proxy.execute();
		if ("success".equals(result)) {
			TestAction action = (TestAction) proxy.getAction();
			System.out.println("\nReturn Success.................");
			System.out.println("Return:Return Title is "+action.getModel().getTitle());
		}
		if ("failed".equals(result))
		{
			TestAction action = (TestAction) proxy.getAction();
			System.out.println("\nReturn Failed.................");
			System.out.println("Return:Return Title is "+action.getModel().getTitle());			
		}
	}
}</pre><br /><br /><span style="color: red">刚刚学习Xwork2,本来想学struts2 发现需要xwork基础，个人认为学习xwork一是理解它的拦截器机制，二是理解它的ValueStack机制，准备写个xwork2学习小结，希望大家多指点。</span>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/57160#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 03 Mar 2007 19:24:35 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/57160</link>
        <guid>http://jamesby.javaeye.com/blog/57160</guid>
      </item>
      <item>
        <title>深入了解WebLogic的类装载机制详解</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/56794" style="color:red;">http://jamesby.javaeye.com/blog/56794</a>&nbsp;
          发表时间: 2007年03月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://publish.it168.com/2005/1109/20051109056401.shtml" target="_blank">http://publish.it168.com/2005/1109/20051109056401.shtml</a><br />作者：chinaitlab <br />【IT168 编程开发】如果大家对一般类的装载器熟悉的话，就知道在java中类的装载采用“代理机制”，即子装载器如果需要装载一个类文件，首先会将此任务提交给父装载器，如果父装载器找不到此类文件，才有子装载器来装载类文件，如果子装载器也找不到，那么就会报告ClassNotFoundException异常。下面简单谈一下我对weblogic server的类装载器原理的了解，希望能和大家分享。<br />　　<br />　<strong>　1．Weblogic允许定制的类装载器，同时也有一个默认的类装载器。其默认的装载器的结构分层如下：</strong><br />　　 <br /><pre name="code" class="java">
             Application ClassLoader 装载所有的EJB
                |                   |
                |                   | 
Web Application 1 ClassLoader   Web Application 2 ClassLoader
                |                   | 
                |                   |
       JSP 1 ClassLoader          JSP 2 ClassLoader</pre><br /> <br />　  <br /><br /><br />　　当部署一个应用的时候，weblogic server会自动创建一个具有层次结构的类装载器。在图中，a.Application Classloader负责装载应用中的所有的EJB JAR文件；<br />　　<br />　　b.Web Application Classloader负责装载所有的Web application 中的WAR 文件（所有得jsp文件除外）；<br />　　<br />　　c.Jsp Classloader 负责装载Web application 中的所有的jsp 文件；<br />　　<br />　　这样的分层结构有一个好处，就是在Jsp，Servlet中可以直接访问EJB的接口。这种上层装载EJB,下层装载servlet等，最下面装载jsp文件的结构，使得经常变动的jsp，servlet等可以被重新装载而不会涉及到EJB层。<br />　　<br />　　在这种默认的类装载器结构下，有一点需要提出的是：<br />　　<br />　　a. 我们的应用必须打包成一个EAR文件，才会允许我们应用中的jsp和servlet文件直接访问ejb;如果将WAR与JAR文件分别打包。Weblogic server会为他们分别生成一个类装载器，作为兄弟节点，这时如果需要在jsp或者servlet中使用ejb,就必须将EJB的Home接口与remote接口打包到WAR中才可以。后面这种情况，适合用在将EJB的客户端和EJB部署在不同的JVM中；<br />　　<br />　　b.web application classloader中，不会装载jsp文件，jsp文件由web application classloader的子装载器Jsp classloader负责装载，因为jsp文件经常的变动，通过为jsp设立一个单独的classloader可以避免对jsp的装载影响到其他的java class或者ejb；<br />　　<br />　　默认装载器的优点：<br />　　<br />　　a. 调用ejb的时候可以采用call-by-referrence的方式；<br />　　<br />　　b. 允许web module独立的装载，不影响其它的web module;<br />　　<br />　　通过在将整个应用打包成一个EAR文件，可以方便的不用再web module中包含EJB的home和remote接口，就可以方便的通过call-by-referrence来调用ejb;<br />　　<br /><strong>　　2. 定制classloader</strong><br />　　<br />　　如果觉得默认的类装载器不能满足需要，weblogic server支持定制的类装载器。在weblogic的文档中指出，自定义的classloader多用于开发者使用，当应用发布之后，不推荐使用。自定义的类装载器通过xml文件来描述。描述文件放在weblogic-application.xml中。Weblogic官方提供的DTD描述文件如下：<br />　　<br /><pre name="code" class="java">　　&lt;classloader-structure>
　　&lt;module-ref>
　　&lt;module-uri>ejba.jar&lt;/module-uri>
　　&lt;/module-ref>
　　&lt;module-ref>
　　&lt;module-uri>webc.war&lt;/module-uri>
　　&lt;/module-ref>
　　&lt;classloader-structure>
　　&lt;module-ref>
　　&lt;module-uri>weba.war&lt;/module-uri>
　　&lt;/module-ref>
　　&lt;/classloader-structure>
　　&lt;classloader-structure>
　　&lt;module-ref>
　　&lt;module-uri>ejbc.jar&lt;/module-uri>
　　&lt;/module-ref>
　　&lt;module-ref>
　　&lt;module-uri>webb.war&lt;/module-uri>
　　&lt;/module-ref>
　　&lt;classloader-structure>
　　&lt;module-ref>
　　&lt;module-uri>webd.war&lt;/module-uri>
　　&lt;/module-ref>
　　&lt;/classloader-structure>
　　&lt;classloader-structure>
　　&lt;module-ref>
　　&lt;module-uri>ejbb.jar&lt;/module-uri>
　　&lt;/module-ref>
　　&lt;/classloader-structure>
　　&lt;/classloader-structure>
　　&lt;/classloader-structure></pre>　　<br />　　通过我们给出的配置文件，我们自定义的classloader的层次结构如下图：<br />　　 <br /><br />　  <br /><br /><br />　　在J2EE的规范中明确的指出，J2EE应用不应该依赖于任一个给定的类装载器。所以，我们自定义的类装载器，在开发过程中还是可以使用的，但一定不要应用于发布后的应用中。<br />　　<br />　　自定义的类装载器有如下得限制：<br />　　<br />　　a.不能够装载servlet;<br />　　<br />　　b.嵌套的深度最大为3，也就是说，最多只能够嵌套三层；<br />　　<br />　　c.自定义装载器的module类型仅限于 Web和 EJB这两种；<br />　　<br />　　d.Jsp Classloader不受此自定义类装载器的影响，它永远都是web module的子类装载器；<br />　　<br />　　相同的类可能导致部署异常；<br />　　<br />　　在自定义的类装载器中，如果要使用EJB，就必须将EJB的home和remote接口打包到相应的web module中去；<br />　　<br /><strong>　　3．Ejb的单独加载</strong><br />　　<br />　　有时候我们可能需要单独加载某个EJB,这个时候我们可以通过以下两种方法来实现：<br />　　<br />　　第一：将应用需要的jar文件放在APP-INF/lib中，或者将类文件放在APP-INF/classes中，这些类文件和JAR文件会被root classloader进行装载，可以被多个应用共享；<br />　　<br />　　第二：可以通过META-INF/MANIFEST.MF文件来指定需要的classes。通常的用法是在META-INF/MANIFEST.MF文件中增加Class-Path:一行。举例如下：<br />　　<br />　　Class-Path:/d:ejb/add.jar<br />　　<br />　　这样就会在当前的jar包中可以找到我们需要的add.jar文件。需要说明的是，在Class-Path:行的最后一定要有一个换行，否则会发生错误。还有，通过Class-Path只能指定本地的JAR文件。<br />　　<br />　　如果能对应用服务器的类装载原理有了较清楚地了解，会对我们的应用移植，在开发中避免不必要的类装载的错误会有很大的帮助。
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/56794#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 01 Mar 2007 19:05:00 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/56794</link>
        <guid>http://jamesby.javaeye.com/blog/56794</guid>
      </item>
      <item>
        <title>我的一次EJB重构过程</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/56708" style="color:red;">http://jamesby.javaeye.com/blog/56708</a>&nbsp;
          发表时间: 2007年03月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>背景</strong><br /><br />因为历史遗留问题，代码写的杂乱无章，没有条理，而且该 EJB 组件 涉及到的 class 与其它系统的完全相同，容易造成混乱，而且该 EJB 需要添加一些新的功能，因此对其进行了重构。<br /><br /><strong>第一步,将EJB 以外的类进行重新规范命名.</strong><br /><br />首先将该EJB的涉及到EJB组件接口以外的Class 全部更换名称,因为EJB的ClassLoader是web ClassLoader的父类,容易发生Class的冲突，组件接口不能更名，有很多系统在使用它。<br /><br /><strong>第二步,将从来不使用的方法从Class中删除</strong><br /><br />因为EJB中的Class不会被其它应用使用,不用考虑JSP是否调用了它,也没有使用自动线程,也不用考虑其它配置文件是否引用. 删除前先将方法更名(当然组件接口相关的方法不能删除),然后编译,当编译不产生任何错误,则可以安全的将该方法删除. 利用这种方法删除了大约上百个方法.<br /><br /><strong>第三步,将EJB Bean的实现抽取出来</strong><br /><br />保持EJB Bean的实现类足够的thin,尽量将所有的业务逻辑抽象为新的Class.这样测试更容易.<br /><br /><strong>第四步,部署EJB 应用</strong><br /><pre name="code" class="java">
ejbmodule.jar
│  commons-logging.properties
│  ejbconfig.properties
│  log4j.properties
│
├─com
│  └─foo.bar.Abc.classes
│
└─META-INF
        ejb-jar.xml
        ejb-modeler-layout.xml
        MANIFEST.MF
        weblogic-cmp-rdbms-jar.xml
        weblogic-ejb-jar.xml</pre><br /><br /><pre name="code" class="java">
ejb-application.ear
│  ejbmodule.jar
│
├─APP-INF
│  └─lib
│          commons-beanutils-1.6.1.jar
│          commons-collections-2.1.1.jar
│          commons-digester.jar
│          commons-lang-2.0.jar
│          commons-logging-1.0.4.jar
│          log4j-1.2.8.jar
│          xercesImpl.jar
│          xml-apis.jar
│
└─META-INF
        application.xml
        MANIFEST.MF</pre>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/56708#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 01 Mar 2007 12:13:00 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/56708</link>
        <guid>http://jamesby.javaeye.com/blog/56708</guid>
      </item>
      <item>
        <title>如何防止用户恶意的F5刷新操作的问题?</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/55614" style="color:red;">http://jamesby.javaeye.com/blog/55614</a>&nbsp;
          发表时间: 2007年02月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>背景:</strong><br />  问题是这样的,系统持久层采用ibatis架构,系统有几个比较复杂的报表,耗费时间稍微长,不过在3秒以内.<br />   但是在报表页面按 F5 10秒钟则会出现statement timeout 的异常,因此有了如何防止用户恶意刷新的想法.<br /><br /><strong>初步想法</strong><br />   在内存中维护一个类似集合的东西,记录url,userid和访问时间,该集合的数据量维护在一个合理的范围,采用先进先出原则,根据访问时间、url和userid判断用户访问某个url的频繁程度,利用Interceptor从而在用户访问service之前拒绝用户访问!<br /><br /><span style="color: red">   谁能提供一个更好的想法?  </span>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/55614#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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 Feb 2007 18:45:24 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/55614</link>
        <guid>http://jamesby.javaeye.com/blog/55614</guid>
      </item>
      <item>
        <title>自己实现的TransactionManager</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/55288" style="color:red;">http://jamesby.javaeye.com/blog/55288</a>&nbsp;
          发表时间: 2007年02月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>背景：</strong><br /><span style="color: red">目前有一个系统，系统已经写好了，但是要不停的添加新的功能，用Struts，<br />业务逻辑写在Action中，以后可能增加一层Service。<br />业务处理和持久层没有使用任何框架，目前是用Dao担任业务处理加持久层双重操作，<br />但是有些业务处理很复杂，固设计了一个事务处理框架，大家帮我看下有没有线程安全的问题，<br />第一次使用ThreadLocal，请多指教。</span><br /><br /><strong>Connection Holder 代码</strong><br /><br /><pre name="code" class="java">public class ConnectionHolder {
	private Connection connection = null;
	private boolean rollback = false;
	private boolean isreadonly = false;
	
	public boolean isIsreadonly() {
		return isreadonly;
	}

	public void setIsreadonly(boolean isreadonly) {
		this.isreadonly = isreadonly;
	}
	public Connection getConnection() {
		if (null == connection)
			throw new RuntimeException("connection not exist........");
		return connection;
	}

	public void setConnection(Connection connection) {
		this.connection = connection;
	}

	public boolean isRollback() {
		return rollback;
	}

	public void setRollback(boolean rollback) {
		this.rollback = rollback;
	}
}</pre><br /><strong>TransactionManager 代码</strong><br /><pre name="code" class="java">public class TransactionManager {
	private static final Log logger = LogFactory
			.getLog(TransactionManager.class);

	private static ThreadLocal _thread = new ThreadLocal();

	private static void safeCloseConnection(Connection con) {
		try {
			if (null != con)
				con.close();
			con = null;
		} catch (Exception e) {
			logger.error("", e);
		}
	}

	public static void begin() {
		begin(false);
	}

	public static void begin(boolean isReadonly) {
		ConnectionHolder holder = null;
		Connection con = null;
		try {
			con = JNDIUtils.getConnection();

			if (!isReadonly) {
				con.setAutoCommit(false);
			}

			holder = new ConnectionHolder();
			holder.setConnection(con);
			holder.setIsreadonly(isReadonly);

			_thread.set(holder);
		} catch (Exception e) {
			safeCloseConnection(con);
			logger.error("", e);
			throw new RuntimeException();
		}
	}

	private static void commit() {
		ConnectionHolder holder = null;
		Connection con = null;
		try {
			holder = getConnectionHolder();
			con = holder.getConnection();
			if (!holder.isRollback() && !holder.isIsreadonly()) {
				con.commit();
				con.setAutoCommit(true);
			}
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			safeCloseConnection(con);
		}
	}

	public static void end() {
		commit();
	}

	public static void rollback() {
		ConnectionHolder holder = null;
		Connection con = null;
		try {
			holder = getConnectionHolder();
			holder.setRollback(true);
			con = holder.getConnection();
			if (holder.isIsreadonly()) {
				throw new RuntimeException("readonly cannot rollback....");
			}
			con.rollback();
			con.setAutoCommit(true);
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			safeCloseConnection(con);
		}
	}

	private static ConnectionHolder getConnectionHolder() {
		ConnectionHolder holder = (ConnectionHolder) _thread.get();
		if (null != holder)
			return holder;
		throw new RuntimeException("connection holder not exist.......");
	}

	public static Connection openConnection() {
		Connection con = getConnectionHolder().getConnection();
		if (null != con)
			return con;
		throw new RuntimeException("connection not exist.......");
	}
}</pre>		<br /><br /><strong>Action 部分代码</strong><br /><br /><pre name="code" class="java">public ActionForward deleteResourceXqzy(ActionMapping mapping,
		ActionForm form, HttpServletRequest request,
		HttpServletResponse response) {
	try {
		TransactionManager.begin(); //事务开始
		/**
			多次DAO代码调用
			业务处理
			多次DAO代码调用
		*/
	} catch (Exception ex) {
		TransactionManager.rollback(); //事务回滚
		//其它操作
	} finally {
		TransactionManager.end(); //事务提交
		//其它操作
	}
	return mapping.findForward("test");
}</pre><br /><br /><strong>DAO 部分代码</strong><br /><br /><pre name="code" class="java">public static void deleteResourceZyfb() throws Exception {
	String sql = null;
	PreparedStatement ps = null;
	try {
		Connection con = TransactionManager.openConnection();
		sql = "";
		ps = con.prepareStatment(sql);
		ps.executeUpdate();
	} finally {
		safeCloseStatementOrRs(ps);
	}
}</pre>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/55288#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 23 Feb 2007 13:53:28 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/55288</link>
        <guid>http://jamesby.javaeye.com/blog/55288</guid>
      </item>
      <item>
        <title>关于Service和DAO层的功能划分的迷惑</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/54260" style="color:red;">http://jamesby.javaeye.com/blog/54260</a>&nbsp;
          发表时间: 2007年02月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Service 层的代码<br /><br /><pre name="code" class="java">public class GeneralService extends AbstractService {
	private GeneralDao generalDao;

	public void setGeneralDao(GeneralDao generalDao) {
		this.generalDao = generalDao;
	}

	public void saveResourceSale(ResourceItemFormbean resourceItem)
			throws Exception {
		generalDao.saveResourceSale(resourceItem);
	}

	public List selectTodayResource(Map params) throws Exception {
		return generalDao.selectTodayResource(params);
	}

	public List selectTdPrintInfo(Integer ddid, Integer linkmanid)
			throws Exception {
		return generalDao.selectTdPrintInfo(ddid, linkmanid);
	}

	public List selectTdPrintItems(Integer ddid) throws Exception {
		return generalDao.selectTdPrintItems(ddid);
	}

	public List selectTodayBuy(Map params) throws Exception {
		return generalDao.selectTodayBuy(params);
	}

	public List selectStockKgzy(Integer ptid, Integer prodid, Integer cmdeptid,Integer page)
			throws Exception {
		return generalDao.selectStockKgzy(ptid, prodid, cmdeptid,page);
	}
	
	public List selectStockXqzy(Integer ptid, Integer prodid, Integer cmdeptid,
			Integer page) throws Exception {
		return generalDao.selectStockXqzy(ptid, prodid, cmdeptid, page);
	}

	public void deletePublishedResource(Integer pkid) throws Exception {
		generalDao.deletePublishedResource(pkid);
	}	
	
	public void saveXqResourcePublish(XqZyfbModel data) throws Exception {
		generalDao.saveXqResourcePublish(data);
	}
	
	public XqZyfbModel selectXqResourceDetail(Integer pkid) throws Exception {
		return generalDao.selectXqResourceDetail(pkid);
	}	
}</pre><br /><br />DAO 层的代码<br /><br /><pre name="code" class="java">public class GeneralDao extends AbstractDao {
	public void saveResourcePublish(ZyfbModel data) throws Exception {
		getSqlMapClientTemplate().update("MainProcedure.saveResourcePublish",
				data);
	}

	public void updateResourcePublish(ZyfbModel data) throws Exception {
		getSqlMapClientTemplate().update("MainProcedure.updateResourcePublish",
				data);
	}
	
	public void deletePublishedResource(Integer pkid) throws Exception {
		getSqlMapClientTemplate().update("MainProcedure.deletePublishedResource",
				pkid);
	}	
	

	public List selectStockXqzy(Integer ptid, Integer prodid, Integer cmdeptid,
			Integer page) throws Exception {
		Map params = new HashMap();
		params.put("ptid", ptid);
		params.put("prodid", prodid);
		params.put("cmdeptid", cmdeptid);
		params.put("row", new Integer(15));
		params.put("page", page);
		return getSqlMapClientTemplate().queryForList(
				"MainProcedure.selectStockXqzy", params);
	}	
	
	public void saveXqResourcePublish(XqZyfbModel data) throws Exception {
		getSqlMapClientTemplate().update("MainProcedure.saveXqResourcePublish",
				data);
	}	
	
	public XqZyfbModel selectXqResourceDetail(Integer pkid) throws Exception {
		return (XqZyfbModel) getSqlMapClientTemplate().queryForObject(
				"MainProcedure.selectXqResourceDetail", pkid);
	}
}</pre><br /><br /><span style="color: red">迷惑的是在上面的代码中，Service 并没有什么业务逻辑，似乎可有可无，是否上面的代码可以将Service层省略，直接在DAO层操作和事务拦截，只有涉及到具体业务逻辑的时候使用Service,当然这会造成Controller和DAO层之间的紧耦合，大家在项目中遇到如上情况都是如何做的？</span>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/54260#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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>Tue, 13 Feb 2007 17:27:30 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/54260</link>
        <guid>http://jamesby.javaeye.com/blog/54260</guid>
      </item>
      <item>
        <title>Spring MutiActionController实现FormController在Controller中的代码事例</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/53940" style="color:red;">http://jamesby.javaeye.com/blog/53940</a>&nbsp;
          发表时间: 2007年02月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">		public ModelAndView handelXqResourcePublish(HttpServletRequest request,
			HttpServletResponse response) throws ServletException {
		Map model = new HashMap();
		try {
			//绑定
			XqZyfbFormBean formBean = new XqZyfbFormBean();
			BindException errorModule = bindObject(request, formBean,
					new XqzyfbValidator());
			if (errorModule.hasErrors())
				formBean.setOperation(XqZyfbFormBean._VIEW);
			
			//取得绑定后模型
			model = errorModule.getModel();
			
			//插入或者更新
			if (XqZyfbFormBean._UPDATE.equals(formBean.getOperation())) {
				XqZyfbModel pojo = new XqZyfbModel();
				pojo.setPkid(formBean.getPkid());
				pojo.setCustname(formBean.getCustname());
				pojo.setPtid(formBean.getPtid());
				pojo.setProdid(formBean.getProdid());
				pojo.setPcname(formBean.getPcname());
				pojo.setLen(formBean.getLen());
				pojo.setSl(formBean.getSl());
				pojo.setDj(formBean.getDj());
				pojo.setJhadr(formBean.getJhadr());
				pojo.setJhdt(formBean.getJhdt());
				pojo.setNote(formBean.getNote());
				pojo.setCmdeptid(new Integer(getUser(request).getCmdeptid()));
				pojo.setLinkmanid(getUser(request).getLinkmanid());
				generalService.saveXqResourcePublish(pojo);
				model.put("errMsg", "操作成功！");
				model.put("url", "/cm/resource/stockXqResource.do?ptid="
						+ formBean.getParamptid() + "&prodid="
						+ formBean.getParamprodid() + "&cmdeptid="
						+ formBean.getParamcmdeptid());
				return new ModelAndView("openerlocation", model);				
			}
			
			//修改取数据
			if (null!=formBean.getPkid()&&formBean.getPkid().intValue()>0)
			{
				XqZyfbModel pojo = generalService.selectXqResourceDetail(formBean.getPkid());
				formBean.setPkid(pojo.getPkid());
				formBean.setCustname(pojo.getCustname());
				formBean.setPtid(pojo.getPtid());
				formBean.setProdid(pojo.getProdid());
				formBean.setPcname(pojo.getPcname());
				formBean.setLen(pojo.getLen());
				formBean.setSl(pojo.getSl());
				formBean.setDj(pojo.getDj());
				formBean.setJhadr(pojo.getJhadr());
				formBean.setJhdt(pojo.getJhdt());
				formBean.setNote(pojo.getNote());				
			}
			
			//新增准备数据
			model.put("prodtypes", generalService.selectProductType());
			model.put("products", generalService.selectProduct());
			model.put("selectproducts", generalService.selectProduct());
		} catch (Exception e) {
			log.error("", e);
			return new ModelAndView("error");
		}
		return new ModelAndView("index_XqResourcePublish", model);
	}	</pre><br /><br /><pre name="code" class="java">public class ResourceItemValidator extends AbstractValidator {
	public void validate(Object obj, Errors errors) {
		ResourceItemFormbean formBean = (ResourceItemFormbean) obj;
		if (null == formBean.getBatid() || formBean.getBatid().intValue() &lt;= 0) {
			errors.rejectValue("batid", "batid.required", null, "default message!");
		}
		if (ResourceItemFormbean._SUBMIT.equals(formBean.getAction())) {

			if (null == formBean.getCustid()
					|| formBean.getCustid().intValue() &lt;= 0) {
				errors
						.rejectValue("custid", "custid.required", null,
								"default message!");
			}
			if (null == formBean.getJs() || formBean.getJs().intValue() &lt;= 0) {
				errors.rejectValue("js", "custid.required", null,
						"default message!");
			}
			if (null == formBean.getSl() || formBean.getSl().doubleValue() &lt;= 0) {
				errors.rejectValue("sl", "custid.required", null,
						"default message!");
			}
			if (null == formBean.getDj() || formBean.getDj().intValue() &lt;= 0) {
				errors.rejectValue("dj", "dj.required", null,
						"default message!");
			}
		}
	}
}</pre><br /><br /><pre name="code" class="java">&lt;%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
&lt;%@ taglib prefix="c" uri="/WEB-INF/c.tld" %>
&lt;%@ taglib prefix="fmt" uri="/WEB-INF/fmt.tld" %>
&lt;%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
&lt;script language="javascript">
&lt;!--
	window.onload=function(){
		form = document.cmForm;
		if (tper>0) form.sl.readOnly=true;
		var error = "";
		&lt;spring:bind path="command.*">
		    &lt;c:forEach items="${status.errorMessages}" var="errorMessage">
		          error=error+"&lt;c:out value="${errorMessage}"/>\n";
		    &lt;/c:forEach>
		&lt;/spring:bind>
		if (""!=error)
		{
			alert(error);
		}				
	}
-->
&lt;/script>
&lt;form:form commandName="command" name="cmForm" action="/cm/resource/resourceSale.do">
	&lt;form:hidden path="batid"/>
	&lt;input type="hidden" name="action" value="submit">
	&lt;form:select path="custid" cssStyle="width:100%">  
		&lt;form:option value="" label=""/>  
		&lt;form:options items="${customer}" itemValue="custid" itemLabel="name"/>  
	&lt;/form:select>  	
	&lt;form:input path="address" cssStyle="width:100%"/>
	&lt;form:input path="js" cssStyle="width:100%" onblur="calculatSl();"/>
	&lt;form:input path="sl" cssStyle="width:100%" onblur="calculatJe();"/>
	&lt;form:input path="dj" cssStyle="width:100%" onblur="calculatJe();"/>
	&lt;form:input path="je" cssStyle="width:100%" readonly="true"/>
	&lt;form:textarea path="memo" cssStyle="width:100%" rows="2"/>
	&lt;input type="button" name="btnOK" class="cbutton" onclick="doSubmit();" value="确定">
	&lt;input type="button" name="btnCancle" onclick="window.close();" class="cbutton" value="取消">
&lt;/form:form></pre>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/53940#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 12 Feb 2007 12:11:06 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/53940</link>
        <guid>http://jamesby.javaeye.com/blog/53940</guid>
      </item>
      <item>
        <title>关于Service调用Service 的思考</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/53724" style="color:red;">http://jamesby.javaeye.com/blog/53724</a>&nbsp;
          发表时间: 2007年02月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          以前做软件都是随便写几个Service,纯粹为了Service而Service,当某天突然发现我的两个Service竟然需要互相访问,于是乎开始考虑如何设计Service,特别是Service之间的依赖关系如何设计的问题,因此偶认为软件Service层的设计应该重点放在两个方面:<br />一是Service 功能划分的设计；二是Service 与 Service 之间的依赖关系的设计。<br />其中,Service与Service之间依赖关系的设计又分如下几种:<br /><br /><strong>一是继承关系依赖</strong><br /><pre name="code" class="java">    public class ObjectA extends ObjectB{
    }</pre><br /><strong>二是属性关系依赖</strong><br /><pre name="code" class="java">    public class OjbectA{
       private ObjectB b;
       public void setB(ObjectB b){
          this.b = b;
       } 
       public void method(){
          b.abc();
       }
    }</pre><br /><br /><strong>三是参数方法参数关系依赖</strong><br /><pre name="code" class="java">    public class ObjectA{
       public void method(ObjectB b){
           b.abc();
       }
   }</pre><br /><br /><span style="color: red">大家对Spring已经很熟悉了,相信前两种大家用的很多,第三种在开源框架用的比较多.</span>
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/53724#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></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, 10 Feb 2007 20:04:00 +0800</pubDate>
        <link>http://jamesby.javaeye.com/blog/53724</link>
        <guid>http://jamesby.javaeye.com/blog/53724</guid>
      </item>
      <item>
        <title>关于FastClassByCGLIB$$c8ef9cf1.invoke(&lt;generated&gt;)出错信息的解释</title>
        <author>jamesby</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jamesby.javaeye.com">jamesby</a>&nbsp;
          链接：<a href="http://jamesby.javaeye.com/blog/53534" style="color:red;">http://jamesby.javaeye.com/blog/53534</a>&nbsp;
          发表时间: 2007年02月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          软件采用SpringMVC+Spring+iBatis进行设计的,在Service出现NullPointer异常的时候会提示FastClassByCGLIB$$c8ef9cf1.invoke(&lt;generated>),这属于正常情况,检查Service层的出错代码,排除代码错误就可以了.
          <br/>
          <span style="color:red;">
            <a href="http://jamesby.javaeye.com/blog/5353