2007年9月29日星期六

敏捷开发(一)

敏捷原则及最佳实践:
  1. 如果你发现自己在"迭代"项目中出现开发前确认大多数需求,编程前试图创建完整、详细的规格说明或UML模型和设计,那么说明瀑布思维已经在无情的折磨着这个项目了。无论如何声称,这都不是正常的迭代或UP项目。
  2. 软件通常不是可预知的或可以大规模制造的。因此,变更对于软件项目来说是永恒的,反馈和改写是成功的关键要素。
  3. UP提倡风险驱动(risk-driven)与客户驱动(client-driven)相结合的迭代计划。这意味着早期的迭代目标要能够识别和降低最高风险,并且能构造客户最关心的可视化特性。风险驱动迭代开发更为明确地包含了以架构为中心(architecture-centric)迭代开发的实践,意味着 早期迭代要致力于核心架构的构造、测试和稳定。因为没有稳固的架构就会带来高风险。
  4. 采用敏捷方法并不意味着不进行建模,这是错误的理解。
  5. 建模和模型的目的主要用于理解和沟通,而不是构建文档。
  6. 只需对设计空间中不常见、困难和棘手的一小部分问题建模和应用UML。简单的设计问题可以推延到编程阶段,在编程和测试过程中解决这些问题。
  7. 尽可能使用简单的工具。因为不需要耗费精力在精美的文档上。
  8. 建模的目的是发现、理解和共享大家的理解。因此,不要单独建模,小组成员要轮流画草图,以使每个人参与其中。
  9. 并行地创建模型。即同时开发类图和交互图,不断交替。
  10. 使用简单常用的UML元素。
  11. 所有模型都可能是不准确的,将其仅仅视为一种探索的过程。
  12. 开发者应该为 自己进行OO设计建模,而不是交给其他编程者实现。瀑布方法才会这样做。
  13. UP核心思想:短时间定量迭代、进化和可适应性开发。对于整个项目不应有详细的计划。应该制定估计结束日期和主要里程碑的阶段计划,但是不要对这些里程碑详细定义细粒度的步骤。只能预先对一个迭代制定更为详细的计划(迭代计划)。详细计划是由一次次迭代的调整而完成的。
  14. 不断地验证质量,提早、经常和实际地测试。
  15. 在适当的地方使用用例。
  16. 认真管理需求,实行变更请求和配置管理。

UP的四个阶段:
  1. 初始(Inception):大体的构想、业务案例、范围和模糊评估。
  2. 细化(Elaboration):已精化的构想、核心架构的迭代实现、高风险问题的解决、确定大多数需求和范围以及进行更为实际的评估。
  3. 构造(Construction):对遗留下来的风险较低和比较简单的元素进行迭代实现,准备部署。
  4. 移交(Transition):进行beta测试和部署。

不符合敏捷精神的做法:
  1. 在开始设计或实现之前试图定义大多数需求。同样,在开始实现之前试图定义大多数设计;试图在迭代编程和测试之前定义和提交完整的架构。
  2. 在编程之前花费数日获数周进行UML建模,或者认为在绘制UML图和进行设计时要准确完整地定义极其详细的设计和模型。并且,认为编程只是简单机械地将其转换为代码的过程。
  3. 认为初始阶段=需求阶段,细化阶段=设计阶段,构造阶段=实现阶段(瀑布模型的典型做法)。
  4. 认为细化的目的是完整仔细地定义模型,以能够在构造阶段将其转换为代码。
  5. 坚信合适的迭代时间长度为三个月,而不是三周。
  6. 认为采用UP就意味着要完成大量可能的活动和创建大量的文档,并且认为UP是需要遵循大量步骤的、正规和繁琐的过程。
  7. 试图对项目从开始到结束制定详细计划;试图预测所有迭代,以及每个迭代中可能发生的事情。

2007年9月24日星期一

EJB3的Timer Service

代码:
package com.xued.timer;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;

@Stateless
public class TimerBean implements TimerBeanLocal {

    @Resource
    private TimerService ts;

    public void cancelAllSchedule() {
        for (Object obj : ts.getTimers()) {
            Timer timer = (Timer) obj;
            timer.cancel();
        }
    }

    public void repeatSchedule() {
        long start = 5000;
        ts.createTimer(start, 9000, null);
        System.out.println("TimerBean: Timer created for first expire after " + start + "ms");
    }

    @Timeout
    public void handleTimeout(Timer timer) {
        System.out.println("TimerBean: handle timeout occured ");
    }
}

cancelAllSchedule()方法用于在设定Timer之前先取消所有关联到这个EJB的Timer,如果不这样做,则容器会将上次运行的Timer关联到这个EJB。利用这个特性,如果Timer的策略不会改变的话,则repeatSchedule()方法只需要在初次部署的时候调用一次就够了,下次重启动的时候,容器会记住你设置的策略,并自动应用到这个EJB上面。
@Timeout指定Timer到点的时候需要执行的方法。
另外,第一次部署TimerBean的时候需要调用repeatSchedule()方法来激活Timer,这就需要一个客户端,手工执行过于麻烦。在JBoss里可以写一个启动时自动执行的管理Bean,代码如下:

接口
package com.xued.timer;

import org.jboss.annotation.ejb.Management;

@Management
public interface TimerInitialService {

    void create() throws Exception;

    void start() throws Exception;

    void stop();

    void destroy();
   
}

实现类
package com.xued.timer;

import javax.ejb.EJB;
import org.jboss.annotation.ejb.Service;

@Service
public class TimerInitialServiceImpl implements TimerInitialService{

    @EJB
    TimerBeanLocal timerbean;
   
    public void create() throws Exception {
        System.out.println("TimerInitialService Started!");
        timerbean.cancelAllSchedule();
        timerbean.repeatSchedule();
    }

    public void start() throws Exception {
    }

    public void stop() {
    }

    public void destroy() {
    }

}

这样启动的时候,就会自动去调用
cancelAllSchedule()和repeatSchedule()两个方法,Timer就被激活了。

2007年9月20日星期四

JBoss 4 设置管理台密码访问

一、用户名密码设置:
$JBOSS_HOME/server/all/conf/props/jmx-console-users.properties,修改jmx-console用户名密码,文件内容格式为用户名=密码
$JBOSS_HOME/server/all/deploy/management/console-mgr.sar/web-console.war/WEB-INF/classes/web-console-users.properties,修改web-console用户名密码,文件内容格式为用户名=密码

二、jmx-console设置:
$JBOSS_HOME/server/all/deploy/jmx-console.war/WEB-INF/web.xml
取消如下部分的注释:
<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAdaptor</web-resource-name>
<description>An example security config that only allows users with the
role JBossAdmin to access the HTML JMX console web application
</description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>JBossAdmin</role-name>
</auth-constraint>
</security-constraint>
$JBOSS_HOME/server/all/deploy/jmx-console.war/WEB-INF/jboss-web.xml
取消如下部分的注释:
<security-domain>java:/jaas/jmx-console</security-domain>

三、web-console设置:
$JBOSS_HOME/server/all/deploy/management/console-mgr.sar/web-console.war/WEB-INF/web.xml
$JBOSS_HOME/server/all/deploy/management/console-mgr.sar/web-console.war/WEB-INF/jboss-web.xml
修改内容同上。

重启JBoss,打开管理台,点击jmx-console或web-console,会弹出用户名密码对话框,填入刚才第一步设置的值,即可进入管理界面。

2007年9月19日星期三

NetBeans6.0 beta1新功能

切换Java包的查看方式:在项目窗口中点击右键,选择View Java Packages As->list or tree
选择项目文件编码:在项目窗口中,选定项目名称,点击右键,选择Properties,出现的窗口中找到Sources->Encoding下拉菜单,选择编码格式。
快捷键的变化:
alt-Insert 插入自动生成代码,可插入getter,setter,构造方法,重写超类方法等
ctrl-R 一次性修改相同的局部变量名,回车确认
alt-shift-上下箭头 搬移一行
ctrl-shift-Space 快速JavaDoc帮助
ctrl-/ 注释或取消注释
ctrl-shift-T 跳到当前类的JUnit测试类文件
ctrl-shift-I 插入多个导入,自动去除多余的导入
alt-shift-F 重新格式化

2007年9月14日星期五

不同方式访问JBoss Web Service的客户端实现

现有一个部署在JBoss上的Web Service端点:

@WebService(name = "SSO", serviceName="SSOService", targetNamespace="http://edxu")
@SOAPBinding(style=SOAPBinding.Style.RPC)
public interface SSO {
@WebMethod
public String login(String userName, String password);
}

一. 利用JBoss本身提供的WS库进行访问

运行需要导入$JBOSS_HOME/server/all/deploy/jbossws.sar下的jar包
客户端代码如下:

private static final String WSDL = "http://localhost:8080/SSOBeanService/SSOBean?wsdl";
private static final String NAMESPACE = "http://edxu";
private static final String SVCNAME = "SSOService";
private static final String PORT = "SSOPort";

Service service = Service.create(new URL(WSDL), new QName(NAMESPACE, SVCNAME));
SSO ssoBean = (SSO)service.getPort(new QName(NAMESPACE, PORT), SSO.class);//也可以不指定Port,只用Class一个参数

以上的代码可以获得一个SSO接口的实例。

二. 利用Sun的JAX-WS 2.1库进行访问

这种方式要在本地客户端必须建立远端Web Service的本地存根,利用包装类接口进行访问,方便起见最好采用NetBeans根据WSDL的地址自动生成本地存根,方法如下:
在NetBeans中建立一个Java应用程序或者Web应用程序的项目,右键点击项目名称,选择新建文件,选择文件类型为Web服务客户端,填入远程WSDL的地址,选择包,点击完成。即可看到输出中自动生成了本地WSDL文件及包装类。

上面的例子中包装类文件有两个:
SSO.java Web服务接口
SSOService.java 访问代理
代码大致如下:

SSO.java:

@WebService(name = "SSO", targetNamespace = "http://edxu")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface SSO {
@WebMethod
@WebResult(partName = "return")
public String login(
@WebParam(name = "arg0", partName = "arg0")
String arg0,
@WebParam(name = "arg1", partName = "arg1")
String arg1);
}

SSOService.java:

@WebServiceClient(name = "SSOService", targetNamespace = "http://edxu", wsdlLocation = "http://localhost:8080/SSOBeanService/SSOBean?wsdl")
public class SSOService
extends Service{
private final static URL SSOSERVICE_WSDL_LOCATION;

static {
URL url = null;
try {
url = new URL("http://localhost:8080/SSOBeanService/SSOBean?wsdl");
} catch (MalformedURLException e) {
e.printStackTrace();
}
SSOSERVICE_WSDL_LOCATION = url;
}

public SSOService() {
super(SSOSERVICE_WSDL_LOCATION, new QName("http://edxu", "SSOService"));
}

@WebEndpoint(name = "SSOPort")
public SSO getSSOPort() {
return (SSO)super.getPort(new QName("http://edxu", "SSOPort"), SSO.class);
}
}

现在可以写我们的客户端代码了,非常简单,只用一句就可以获得SSO接口的远程实例:

SSO ssoBean = new SSOService().getSSOPort();

以上代码需要导入NetBeans中的Sun JAX-WS 2.1库。

以上代码测试环境为JDK1.5.0_12,JBoss 4.2.1GA,NetBeans 5.5.1。

2007年9月13日星期四

ClassLoader在应用服务器中的问题

一.ClassLoader 在应用服务器中的使用

每一种应用服务器都有自己的Class Loader,而且各个Class Loader的实现方式和层次结构都不太相同。因此在使用和部署应用的时候,需要先了解当前应用服务器的Class Loader的特点,才能知道哪些类库文件应该放到哪个目录下。

总的来说,应用服务器使用class loader的主要目的是为了安全和效率。安全是通过Class Loader将不同的应用互相隔离,使得不同的应用可以有相同的类名,而不互相干扰。效率是通过代理(delegate)模式来使得各个不同的应用如果使 用相同的类库,只在内存中装载一次,节省装载的时间和对内存的开销。

二.问题出现的原因

正是因为代理的模式,导致了上面的问题:在 JES Application Server本身实现中已经使用了大量开源的软件包,例如(org.apache.commons)的各个工具包。在代理模式下,各个Web应用会把类装 载的工作代理给它的上级或上级的上级等等。如果当JES Application Server本身已经装载这些包,那就不会再装载应用中的相同名字的类库了。当应用使用的类库与JES使用的类库有版本冲突的时候,就会造成一些麻烦。

二. JES上的解决方案

在Web应用的部署过程中,只需要在sun-web.xml描述文件中,加上下面的属性值,就能关闭代理的模式,解决上面的问题。

<class-loader>
    <property delegate=false/>
</class-loader>

以上部分参考自:http://developers.sun.com.cn/blog/yutoujava/entry/5

三. JBoss上的解决方案

在EAR应用的部署过程中,只需要在METE_INF/jboss-app.xml描述文件中,加入以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-app>
   <loader-repository loaderRepositoryClass='org.jboss.mx.loading.HeirarchicalLoaderRepository3'>
      sso:loader=sso.ear
      <loader-repository-config configParserClass='org.jboss.mx.loading.HeirarchicalLoaderRepository3ConfigParser '>
         java2ParentDelegaton=true
      </loader-repository-config>
   </loader-repository>
</jboss-app>

HeirarchicalLoaderRepository3的作用是首先在EAR内部查找class,java2ParentDelegaton=true的意思是找不到就委托给父ClassLoader,设为false就会抛出ClassNotFound异常。

四. App ClassLoader原理

此部分内容转贴自:http://www.javaeye.com/article/11

Class Loader的作用范围:

BootStrap Class Loader:

load JRE\lib\rt.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar

Ext Class Loader:

load JRE\lib\ext目录下的库文件, load JRE\classes目录下的类

App Class Loader:

load CLASSPATH变量指定路径下的类

以上的load路径都是写死在JVM的C++源代码里面的,不能改变,详细请见王森的《Java深度历险》

在一个特定的App Server上,Class Loader会继续向下继承,继承的层次会根据不同的App Server有所不同,但是肯定不会变的就是:

EJB Class Loader:

继承自App Class Loader,继承层次根据App Server有所不同,一个EJB Class Loader它的load Class的范围仅限于JAR或者EAR范围之内。

Web App Class Loader:

继承自App Class Loader,继承层次根据App Server有所不同,一个Web App Class Loader:它的load Class的范围在 WEB-INF\lib下的库文件和WEB-INF\classes目录下的class文件。

Web App Class Loader很好理解,大家毕竟用的很多,App Server上的一个Web Application会创建一个Web App Class Loader的实例去负责load class,所以如果你想让Hibernate只在这个Web Application内生效,把它放到WEB-INF\lib下去就好了。

如果你把Hibernate放到了CLASSPATH变量指定的路径下,而你在WEB-INF\lib也放了一份,那么Web App Class Loader由于load范围所限,它会首先找到WEB-INF\lib下的那份Hibernate,按照它的配置来初始化Hibernate。

如果你把Hibernate放到了CLASSPATH变量指定的路径下,但你在WEB-INF\lib什么都没有放,那么Web App Class Loader由于load范围所限,它根本什么都找不到,于是它把load Hibernate的责任交给上一级的Class Loader,这样直到App Class Loader,它找到了Hibernate,按照它的配置来初始化Hibernate。

EJB Class Loader稍微复杂一点,不那么容易理解。App Server会针对每一个EJB包文件创建一个EJB Class Loader的实例,例如:

HelloRobbin.jar
HelloBruce.jar

当你把这两个jar发布到App Server上以后,会创建两个EJB Class Loader的实例,分别去load这两个EJB包,比如说:

CLEJB_Robbin是load HelloRobbin.jar的
CLEJB_Bruce是load HelloBruce.jar的

那么CLEJB_Robbin的load范围就仅仅限于HelloRobbin.jar之内,它load不到HelloRobbin.jar之外的任何文件,当然它也load不到HelloBruce.jar。

说到这里,我相信大家应该已经明白为什么EJB规范不允许EJB有IO操作了吧?因为EJB Class Loader根本找不到jar包之外的文件!!!

如果现在你想实现HelloRobbin.jar和HelloBruce.jar的互相调用,那么该怎么办?他们使用了不同的EJB Class Loader,相互之间是找不到对方的。解决办法就是使用EAR。

现在假设HelloRobbin.jar和HelloBruce.jar都使用了Hibernate,看看该怎么打包和发布:

HelloEJB.ear
|------ HelloRobbin.jar
|------ HelloBruce.jar
|------ Hibernate2.jar
|------ pojo.jar (定义所有的持久对象和hbm文件的jar包)
|------ cglib-asm.jar
|------ commons-beanutils.jar
|------ commons-collections.jar
|------ commons-lang.jar
|------ commons-logging.jar
|------ dom4j.jar
|------ odmg.jar
|------ log4j.jar
|------ jcs.jar
|------ hibernate.properties
|------ log4j.properties
|------ cache.ccf
|------ META-INF\application.xml (J2EE规范的要求,定义EAR包里面包括了哪几个EJB)

除此之外,按照EJB规范要求,HelloRobbin.jar和HelloBruce.jar还必须指出调用jar包之外的类库的名称,这需要在jar包的manifest文件中定义:

HelloRobbin.jar
|------ META-INF\MANIFEST.MF

MANIFEST.MF中必须包括如下一行:

Class-Path: log4j.jar hibernate2.jar cglib-asm.jar commons-beanutils.jar commons-collections.jar commons-lang.jar
commons-logging.jar dom4j.jar jcs.jar odmg.jar jcs.jar pojo.jar

这样就OK了,当把HelloEJB.ear发布到App Server上以后,App Server创建一个EJB Class Loader实例load EAR包里面的EJB,再根据EJB的jar包里面的MANIFEST.MF指出的Class-Path去寻找相应的jar包之外的类库。

所以一个EAR包有点类似一个Web Application,EJB Class Loader的load范围也就是EAR范围之内,它load不到EAR之外的文件。除非把Hibernate定义到CLASSPATH指定的路径下,在 这种情况下,EJB Class Loader找不到Hibernate,只能交给上一级的Class Loader,最后由App Class Loader找到Hibernate,进行初始化。

由于EAR这样load Class规则,假设Robbin和Bruce都在同一个Weblogic上运行自己的网站,而我们都不希望自己的程序里面的Hibernate配置被对方的搞乱掉,那么我们就可以这样来做:

Robbin's Website:

Robbin.ear
|-------- robbin.war (把Web Application打包)
|-------- robbin.jar (把开发的EJB打包)
|-------- Hibernate2.jar
..........................
|-------- META-INF\application.xml

Bruce's Website:

Bruce.ear
|-------- bruce.war (把Web Application打包)
|-------- bruce.jar (把开发的EJB打包)
|-------- Hibernate2.jar
..........................
|-------- META-INF\application.xml

这样在同一个App Server上运行,就可以互相不干扰。

EJB3调用的几种方式

转贴自:http://developers.sun.com.cn/blog/yutoujava/entry/4

一. 同一个应用中的EJB调用

在同一个EAR应用当中的EJB调用是EJB最常见的调用。在同一个EAR中既有EJB,又有Servlet。在Servlet中对EJB的调用比较简单。而且在开发EJB的时候,可以使用EJB的本地接口来提高性能。下面是一个EJB3.0调用的代码片断:

 @EJB
    private NewSessionRemote newSessionBean;

    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Servlet MyServlet</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Returned string from Session bean is " + newSessionBean.sayHello("Wang Yu")  + "</h1>");
        out.println("</body>");
        out.println("</html>");
        out.close ();
    }

二. 在同一个Glassfish实例不同应用的EJB调用

在同一个Glassfish实例上(同一个JVM)可以部署多个应用,其中应用A中部署了EJB,而应用B中的Servlet可以调用应用A中的EJB。这种情况下,Servlet的调用代码完全和上面的一样,有一些区别是:

  1. EJB的调用必须通过Remote接口。
  2. 必须将EJB的Remote接口类放在本地的类路径下(WEB-INF/lib的jar文件或WEB-INF/classes下)

三.在应用容器中的客户端调用(ACC)

通过ACC来进行客户端的调用,在Glassfish种有详细的描述,请见(http://docs.sun.com/app/docs/doc/819-3659/6n5s6m5a6?q=java+ee+5&a=view)。

四. 独立的客户端调用EJB

如果是在一个独立的Java客户端对EJB进行调用,那么必须做到以下几步:

  1. EJB的调用必须通过Remote接口。
  2. 必须将EJB的Remote接口类放在本地的类路径下
  3. 类路径下还要包括其他的几个jar文件,这几个jar文件都在Glassfish的lib目录下,包括javaee.jar,appserv-rt.jar,appserv-ext.jar和appserv-deploy-client.jar
  4. 在Java命令中需要包括以下的参数,例如:

    java -Dorg.omg.CORBA.ORBInitialHost=com.acme.Host1(指定Glassfish的主机名或IP地址,缺省是localhost)
     -Dorg.omg.CORBA.ORBInitialPort=9876 (指定EJB所监听的IIOP端口,缺省是3700) 

  5. 在代码中进行显示的EJB lookup和调用。例如:
    ....... 
    public static void main(String[] args) {
            try {
                InitialContext ic =new InitialContext();
                NewSessionRemote sayhello = (NewSessionRemote) ic.lookup("mypackage.NewSessionRemote");
                String result = sayhello.sayHello("dad");
                System.out.println(result);
            } catch (NamingException ex) {
                ex.printStackTrace();
            }       
        }
    ........

五. 在别的Web容器中调用(Tomcat)

在别的Web容器中的Servlet和JSP也可以对Glassfish上的EJB进行远程调用,这个调用从原理上就和在(四)中介绍的"独立的客 户端对EJB调用"一样,在调用的代码上有一点区别,就是在这些Web容器中通常对JDNI容器有自己的实现方法和参数设置,需要强制改变这些设置才能成 功调用Glassfish中的EJB,解决方案是加入以下代码:

 Properties props = new Properties();
 props.setProperty("java.naming.factory.initial",  "com.sun.enterprise.naming.SerialInitContextFactory");
 props.setProperty ("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
 props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
 props.setProperty("org.omg.CORBA.ORBInitialHost", "puma.prc.sun.com");
 props.setProperty ("org.omg.CORBA.ORBInitialPort", "6262");

 InitialContext ic = new InitialContext(props);

当然,EJB的Remote接口和那几个Glassfish所带的应用服务器相关的Jar文件也要放到相应的类路径中。

六. 在不同的Glassfish容器之间调用

如果在(五)的场景中,调用者和被调者的应用都在Glassfish上,调用过程可以大大简化。在调用的Web应用中可以通过"corba interop"的技术对远端的EJB进行引用,而在代码中不需要进行任何的修改,就像在同一个Glassfish实例上的EJB一样。例如,在调用者的 Servlet中:

package wangyu;

import java.io.*;
import java.net.*;
import javax.ejb.EJB;

import javax.servlet.*;
import javax.servlet.http.*;
import mypackage.NewSessionRemote;

/**
 *
 * @author wangyu
 * @version
 */
public class CallRemote extends HttpServlet {

    @EJB
    private NewSessionRemote newSessionBean;
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Servlet CallRemote</title>");
        out.println("</head>");
        out.println("<body>");
       out.println("<h1>Returned string from Session bean is " + newSessionBean.sayHello("Wang Yudasd")  + "</h1>");
        out.println("</body>");
        out.println("</html>");
        out.close();
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
    

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
   
    /** Returns a short description of the servlet.
     */
    public String getServletInfo() {
        return "Short description";
    }
    // </editor-fold>
}

这些代码和(一)中完全一样。但是在sun-web.xml中,需要加上EJB引用的配置:

<ejb-ref>
    <ejb-ref-name>wangyu.CallRemote/newSessionBean</ejb-ref-name>
    <jndi-name>corbaname:iiop:puma.prc.sun.com:3700#mypackage.NewSessionRemote</jndi-name>
  </ejb-ref>

在JNDI的名字中指向另外一个Glassfish实例(有可能在另外一台机器上)的地址中的EJB。


2007年9月12日星期三

Java中对Cookie的操作方法

转贴自:http://tmsoft.lsxy.com/index.php?load=read&id=421

1.设置Cookie
1 Cookie cookie = new  Cookie("key" "value");
2 cookie.setMaxAge(60);  //设置60秒生存期,如果设置为负值的话,则为浏览器进程Cookie(内存中保存),关闭浏览器就失效。
3cookie.setPath( "/test/test2");  //设置Cookie路径,不设置的话为当前路径(对于Servlet来说为request.getContextPath() + web.xml里配置的该Servlet的url-pattern路径部分)
4response.addCookie(cookie);

2.读取Cookie
1 1// 该方法可以读取当前路径以及"直接父路径"的所有Cookie对象,如果没有任何Cookie的话,则返回null
2 2Cookie[] cookies = request.getCookies();

3.删除Cookie
1Cookie cookie  = new Cookie(" key"null);
2cookie.setMaxAge(0 ); //设置为0为立即删除该Cookie
3cookie.setPath( "/test/test2");  //删除指定路径上的Cookie,不设置该路径,默认为删除当前路径Cookie
4 response.addCookie(cookie);


4.注意:假设路径结构如下
                         /
                         /test
                         /test/test2
                         /test345
                         /test555/test666

    a. 相同键名的Cookie(值可以相同或不同)可以存在于不同的路径下。
      
    b. 删除时,如果当前路径下没有键为"key"的Cookie,则查询全部父路径,检索到就执行删除操作(每次只能删除一个与自己最近的父路径Cookie)
        FF.必须指定与设定cookie时使用的相同路径来删除改cookie,而且cookie的键名不论大写、小写或大小混合都要指定路径。
        IE.键名小写时,如果当前路径为/test/test2,如果找不到再向上查询/test、/test555、/test345,如果还找不到就查询/ 。(/test555/test666不查询)
             键名大小写混合或大写时,不指定路径则默认删除当前路径,并且不向上查询。

    c. 读取Cookie时只能读取直接父路径的Cookie。
        如果当前路径为/test/test2,要读取的键为"key"。当前路径读取后,还要读取/test,/test读取后,还要读取/

    d.在做Java的web项目时,由于一般的Web服务器(如Tomcat或Jetty)都用Context来管理不同的Web Application,这样对于每个Context有不同的Path,
       在一个Server中有多个Web Application时要特别小心,不要设置Path为/的Cookie,容易误操作。(当然前提是域名相同)

    e.最好也不要在不同路径下使用相同键名的cookie,这样做很容易引起歧义。

    f.为了避免对FF和IE或其他浏览器区分操作,设置cookie时最好指定路径,删除cookie也要指定路径。


Solaris10常用命令

软件包:

安装软件包:pkgadd -d <pkg绝对路径名>
删除软件包:pkgrm <软件包pkg名>
查看软件包:pkginfo
检测当前已经安装在系统上的软件包的内容和属性:pkgchk SUNWladm
列出软件包中文件的内容:pkgchk -v SUNWladm
检查那些文件在安装后被改变了: pkgchk -p /etc/shadow
列出/usr/bin/showrev的相关信息:pkgchk -l -p /usr/bin/showrev

安装补丁包:patchadd 补丁包名
删除补丁包:patchrm 补丁包名
查看补丁包:showrev -p

smpatch analyze 分析补丁包
smpatch download 下载补丁包
smpatch update 全部更新
smpatch add 选择性地更新


Xwindow:


kdmconfig 选择xwindow类型
/usr/X11/bin/xorgconfig 配置xorg.conf

/usr/dt/bin/dtconfig -d (disable auto-start)
/usr/dt/bin/dtconfig -e (enable auto-start)
/usr/dt/bin/dtconfig -kill (kill dtlogin)
/usr/dt/bin/dtconfig -reset (reset dtlogin)
/usr/dt/bin/dtconfig -p (printer action update)
/usr/dt/bin/dtconfig -inetd (inetd.conf /usr/dt daemons)
/usr/dt/bin/dtconfig -inetd.ow (inetd.conf /usr/openwin daemons)

系统:

df -k 硬盘分区使用情况

isainfo -b 查看系统内核32/64位属性
psrinfo -vp 查出物理CPU的数目

主机名:修改后重新启动
/etc/inet/hosts
/etc/hostname.xxx(xxx代表你的网卡的名称)
/etc/nodename
/etc/inet/ipnodes(ipv6协议使用的主机文件)

ifconfig -a 查看IP地址
修改IP地址:修改后重新启动
/etc/hosts
/etc/hostname.xxx
/etc/defaultrouter(默认网关)
/etc/netmasks(掩码)
/etc/inet/ipnodes

DNS设置:
# vi /etc/resolv.conf
nameserver dns_server_ip

查看内存:
vmstat n n
prstat

服务:

svcs -a用于查看所有状态的服务
svcs -x用于查看未正常启动的服务
svcs -l <fmri> 用于查看单个服务的详细信息

svcadm enable fmri -- 启用一个SMF服务,同时运行该服务
svcadm disable fmri -- 禁用一个SMF服务,同时停止该服务
svcadm restart fmri -- 重启一个SMF服务
svcadm refresh fmri -- 刷新一个SMF服务,相当于让服务重新载入配置文件
svcadm mark fmri -- 将SMF服务标记为维护状态
svcadm clear fmri -- 清除SMF服务的维护状态
svcadm milestone milestone -- 进入指定的服务里程碑,相当于进入相应的运行级别

inetadm -e fmri 启用指定的inetd服务
inetadm -d fmri 禁用指定的inetd服务
inetadm -l fmri 列出指定inetd服务的属性
inetadm -p 列出默认inetd服务的属性

Solaris 10 PATH环境变量设置
vi /etc/profile
PATH=$PATH:/sbin:/usr/ccs/bin:/usr/X11/bin:/usr/X11R6/bin:/usr/dt/bin:/usr/openw
in/bin:/usr/sfw/bin:/usr/net/bin:/usr/proc/bin:/usr/local/bin
export PATH

Oracle启动及关闭

启动:
sqlplus /nolog
connect / AS SYSDBA
startup

关闭:
sqlplus /nolog
connect / AS SYSDBA
shutdown immediate

NetBeans常用快捷键

ctrl-E 删除行
ctrl-Backspace 删除前方文本
ctrl-F3 查找词语,高亮显示
alt-shift-H 关闭高亮显示
ctrl-\ 代码辅助
alt-shift-O 查找类
alt-shift-F 生成Import
alt-K 回到上一个编辑位置
shift-Enter 开始一个新行,不拆分
ctrl-Enter 拆分当前行,光标不动
ctrl-shift-T 注释掉选定的块
ctrl-shift-D 取消块注释

psf = public static final
St = String
psvm = public static void main...
sout = System.out.println...
fore = for(Object o : List)...
fori = for(int i=0; i<limit; i+)...
trycatch = try{}catch()...