<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>piaochunzhi</title>
    <description></description>
    <link>http://piaochunzhi.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>transactionAttributes 属性</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/230244" style="color:red;">http://piaochunzhi.javaeye.com/blog/230244</a>&nbsp;
          发表时间: 2008年08月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          PROPAGATION_MANDATORY:   <br />  带有这个特性的方法必须在事务内被调用；否则它会抛出异常（对于远程客户：RemoteException;对于本地会报：EJBException）   <br />    <br />  PROPAGATION_NESTED   :   <br />  这个好象楼主写错了：）   <br />    <br />  PROPAGATION_NEVER：   <br />  被调用的方法必须是事务的一部分。不然就会抛出错误：TransactionRequireException异常（远）或者   RequireException(本地)   <br />    <br />  PROPAGATION_NOT_SUPPORTED：   <br />  表明方法不需要事务，但是可以在事务的范围内执行。   <br />    <br />  PROPAGATION_REQUIRED：这个我想楼主明白知道什么意思了，我不再多说。   <br />    <br />  PROPAGATION_REQUIRED_NEW：表明创建新事务。它永远都不应该运行在已经完成的任务的事物内部   <br />    <br />  PROPAGATION_SUPPORTS：使用它就是不能把事物传递给方法
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/230244#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, 19 Aug 2008 18:56:19 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/230244</link>
        <guid>http://piaochunzhi.javaeye.com/blog/230244</guid>
      </item>
      <item>
        <title>struts2国际化中的properties 的中文编辑</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/230226" style="color:red;">http://piaochunzhi.javaeye.com/blog/230226</a>&nbsp;
          发表时间: 2008年08月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          struts2国际化中的properties 的中文编辑<br /> <br />关于struts2国际化中的properties 的中文编辑, 就不需再用native2ascii 来转换了.<br /><br />要不然得建个bat 文件.<br /><br />cd %工作目录%\src<br />native2ascii -encoding UTF-8 template.properties globalMessages_zh_CN.properties<br /><br />来转换.<br /><br />你也可以<br />下载 PropEdit<br /><br />在eclipse3.x 或 myeclipse6.x   中 Help>>Soft Updates>><br />Find Update Install 添加网址<br />http://propedit.sourceforge.jp/eclipse/updates/<br /><br />选择for Eclipse 3.x<br /><br />下载后,重启IDE. 即可.jp.gr.java_conf.ussiy.app.propedit_4.8.2
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/230226#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, 19 Aug 2008 17:55:59 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/230226</link>
        <guid>http://piaochunzhi.javaeye.com/blog/230226</guid>
      </item>
      <item>
        <title>j2ee笔试题目 servlet笔试题目 jsp 笔试题目  java笔试题目</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/153734" style="color:red;">http://piaochunzhi.javaeye.com/blog/153734</a>&nbsp;
          发表时间: 2008年01月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          1.MVC的各个部分都有那些技术来实现?如何实现?<br />答：MVC是Model－View－Controller的简写。"Model" 代表的是应用的业务逻辑（通过JavaBean，EJB组件实现）， "View" 是应用的表示面（由JSP页面产生），"Controller" 是提供应用的处理过程控制（一般是一个Servlet），通过这种设计模型把应用逻辑，处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。<br /><br />2.J2EE是什么？ <br />答：Je22是Sun公司提出的多层(multi-diered),分布式(distributed),基于组件(component-base)的企业级应用模型(enterpriese application model).在这样的一个应用系统中，可按照功能划分为不同的组件，这些组件又可在不同计算机上，并且处于相应的层次(tier)中。所属层次包括客户层(clietn tier)组件,web层和组件,Business层和组件,企业信息系统(EIS)层。<br /><br />3.J2EE是技术还是平台还是框架？<br />答：J2EE本身是一个标准，一个为企业分布式应用的开发提供的标准平台。<br /> J2EE也是一个框架，包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术。<br /><br />4.STRUTS的应用(如STRUTS架构)<br />答：Struts是采用Java Servlet/JavaServer Pages技术，开发Web应用程序的开放源码的framework。 采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能： <br />一.包含一个controller servlet，能将用户的请求发送到相应的Action对象。 <br />二.JSP自由tag库，并且在controller servlet中提供关联支持，帮助开发员创建交互式表单应用。 <br />三.提供了一系列实用对象：XML处理、通过Java reflection APIs自动处理JavaBeans属性、国际化的提示和消息。<br /><br />5.WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。 <br />答：Web ServiceWeb Service是基于网络的、分布式的模块化组件，它执行特定的任务，遵守具体的技术规范，这些规范使得Web Service能与其他兼容的组件进行互操作。<br />JAXP(Java API for XML Parsing) 定义了在Java中使用DOM, SAX, XSLT的通用的接口。这样在你的程序中你只要使用这些通用的接口，当你需要改变具体的实现时候也不需要修改代码。<br />JAXM(Java API for XML Messaging) 是为SOAP通信提供访问方法和传输机制的API。<br />WSDL是一种 XML 格式，用于将网络服务描述为一组端点，这些端点对包含面向文档信息或面向过程信息的消息进行操作。这种格式首先对操作和消息进行抽象描述，然后将其绑定到具体的网络协议和消息格式上以定义端点。相关的具体端点即组合成为抽象端点（服务）。<br />SOAP即简单对象访问协议(Simple Object Access Protocol)，它是用于交换XML编码信息的轻量级协议。 <br />UDDI 的目的是为电子商务建立标准；UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范，同时也包含一组使企业能将自身提供的Web Service注册，以使别的企业能够发现的访问协议的实现标准。<br /><br />6.C/S 与 B/S 区别：<br />答：有如下八个方面的不同：<br />(1)硬件环境不同: <br />　　C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.<br />　　B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例与电话上网, 租用设备. 信息自己管理. 有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行 <br />(2)对安全要求不同 <br />　　C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用C/S 结构适宜. 可以通过B/S发布部分可公开信息.<br />　　B/S 建立在广域网之上, 对安全的控制能力相对弱, 可能面向不可知的用户。<br />(３)对程序架构不同 <br />　　C/S 程序可以更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑.<br />　　B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上. 比C/S有更高的要求 B/S结构的程序架构是发展的趋势, 从MS的.Net系列的BizTalk 2000 Exchange 2000等, 全面支持网络的构件搭建的系统. SUN 和IBM推的JavaBean 构件技术等,使 B/S更加成熟. <br />(４)软件重用不同 <br />　　C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在B/S要求下的构件的重用性好.<br />　　B/S 对的多重结构,要求构件相对独立的功能. 能够相对较好的重用.就入买来的餐桌可以再利用,而不是做在墙上的石头桌子 <br />(５)系统维护不同  <br />　　C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级. 升级难. 可能是再做一个全新的系统<br />　　B/S 构件组成,方面构件个别的更换,实现系统的无缝升级. 系统维护开销减到最小.用户从网上自己下载安装就可以实现升级. <br />(６)处理问题不同 <br />　　C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关. 应该都是相同的系统<br />　　B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S无法作到的. 与操作系统平台关系最小. <br />(７)用户接口不同 <br />　　C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高<br />　　B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流. 并且大部分难度减低,减低开发成本. <br />(８)信息流不同 <br />　　C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低<br />　　B/S 信息流向可变化, B-B B-C B-G等信息、流向的变化, 更像交易中心。<br />7.什么是JNDI<br />答：（Java Naming & Directory Interface）JAVA命名目录服务。主要提供的功能是：提供一个目录系统，让其它各地的应用程序在其上面留下自己的索引，从而满足快速查找和定位分布式应用程序的功能。<br /><br />8.什么是JMS<br />答：（Java Message Service）JAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播<br /><br />9.什么是JTA<br />答：（Java Transaction API）JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。<br /><br />10.开发中都用到了那些设计模式?用在什么场合?<br />答：每个模式都描述了一个在我们的环境中不断出现的问题，然后描述了该问题的解决方案的核心。通过这种方式，你可以无数次地使用那些已有的解决方案，无需在重复相同的工作。主要用到了MVC的设计模式。用来开发JSP/Servlet或者J2EE的相关应用。简单工厂模式等。<br /><br />11.、j2ee常用的设计模式？说明工厂模式。<br /> 答：Java中的23种设计模式：<br />Factory（工厂模式），      Builder（建造模式），       Factory Method（工厂方法模式），<br />Prototype（原始模型模式），Singleton（单例模式），    Facade（门面模式），<br />Adapter（适配器模式），    Bridge（桥梁模式），        Composite（合成模式），<br />Decorator（装饰模式），    Flyweight（享元模式），     Proxy（代理模式），<br />Command（命令模式），      Interpreter（解释器模式）， Visitor（访问者模式），<br />Iterator（迭代子模式），   Mediator（调停者模式），    Memento（备忘录模式），<br />Observer（观察者模式），   State（状态模式），         Strategy（策略模式），<br />Template Method（模板方法模式）， Chain Of Responsibleity（责任链模式）<br />工厂模式：工厂模式是一种经常被使用到的模式，根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例，通常这一组类有一个公共的抽象父类并且实现了相同的方法，但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类，该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类，工厂类可以根据条件生成不同的子类实例。当得到子类的实例后，开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。<br /><br />12.UML方面<br />答：标准建模语言UML。用例图,静态图(包括类图、对象图和包图),行为图,交互图(顺序图,合作图),实现图<br /><br />13.RMI<br />RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制，能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。调用这样一个对象时，其参数为 "marshalled" 并将其从本地虚拟机发送到远程虚拟机（该远程虚拟机的参数为 "unmarshalled"）上。该方法终止时，将编组来自远程机的结果并将结果发送到调用方的虚拟机。如果方法调用导致抛出异常，则该异常将指示给调用方。<br /> <br /><br /><br />JAVA 基础<br /><br />1.如何获得数组的长度？<br />数组名.length<br /><br />2.访问修饰符“public/private/protected/缺省的修饰符”的使用类?<br />public :  公共,均可访问<br />private:  私有的,同一个java类中可以访问.子类不能访问.<br />protected: 同一个包中的类都可访问.子类可以访问.<br />缺省,friendly :当前类,同一个包,都可以访问.<br />作用域           当前类       同一package  子孙类       其他package<br />public            √              √                  √             √<br />protected        √              √                  √             ×<br />friendly          √              √                   ×            ×<br />private           √              ×                   ×            ×<br /><br />3.Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类，是否可以implements(实现)interface(接口)?<br />匿名内部类是没有名字的内部类,不能继承其它类,但一个内部类可以作为一个接口,由另一个内部类实现.<br /><br />一、由于匿名内部类没有名字，所以它没有构造函数。因为没有构造函数，所以它必须完全借用父类的构造函数来实例化，换言之：匿名内部类完全把创建对象的任务交给了父类去完成。<br /><br />二、在匿名内部类里创建新的方法没有太大意义，但它可以通过覆盖父类的方法达到神奇效果，如上例所示。这是多态性的体现。<br /><br />三、因为匿名内部类没有名字，所以无法进行向下的强制类型转换，持有对一个匿名内部类对象引用的变量类型一定是它的直接或间接父类类型。<br /><br />new &lt;类或接口> &lt;类的主体><br /><br />匿名类 <br /><br />匿名类是不能有名称的类，所以没办法引用它们。必须在创建时，作为new语句的一部分来声明它们。 <br /><br />这就要采用另一种形式的new语句，如下所示： <br /><br /><br />new &lt;类或接口> &lt;类的主体> <br /><br />这种形式的new语句声明一个新的匿名类，它对一个给定的类进行扩展，或者实现一个给定的接口。它还创建那个类的一个新实例，并把它作为语句的结果而返回。要扩展的类和要实现的接口是new语句的操作数，后跟匿名类的主体。 <br /><br />如果匿名类对另一个类进行扩展，它的主体可以访问类的成员、覆盖它的方法等等，这和其他任何标准的类都是一样的。如果匿名类实现了一个接口，它的主体必须实现接口的方法。 <br /><br />注意匿名类的声明是在编译时进行的，实例化在运行时进行。这意味着for循环中的一个new语句会创建相同匿名类的几个实例，而不是创建几个不同匿名类的一个实例。 <br /><br />从技术上说，匿名类可被视为非静态的内部类，所以它们具有和方法内部声明的非静态内部类一样的权限和限制。 <br /><br />如果要执行的任务需要一个对象，但却不值得创建全新的对象（原因可能是所需的类过于简单，或者是由于它只在一个方法内部使用），匿名类就显得非常有用。匿名类尤其适合在Swing应用程序中快速创建事件处理程序。 <br /><br />exp:<br />return new Contents() {<br />private int i = 11;<br />public int value() { return i; }<br />};<br /><br />这种奇怪的语法要表达的意思是：“创建从Contents衍生出来的匿名类的一个对象”。由new表达式返回的句柄会自动上溯造型成一个Contents句柄。匿名内部类的语法其实要表达的是：<br /><br />class MyContents extends Contents {<br />private int i = 11;<br />public int value() { return i; }<br />}<br />return new MyContents();<br />若试图定义内部类,并想使用在匿名内部类外部定义的一个对象,则编译器要求外部对象必须是final属性.<br />public class Parcel9 {<br />  public Destination <br />  dest(final String dest, final float price) {<br />    return new Destination() {<br />      private int cost;<br />      // Instance initialization for each object:<br />      {<br />        cost = Math.round(price);<br />        if(cost > 100)<br />          System.out.println("Over budget!");<br />      }<br />      private String label = dest;<br />      public String readLabel() { return label; }<br />    };<br />  }<br />  public static void main(String[] args) {<br />    Parcel9 p = new Parcel9();<br />    Destination d = p.dest("Tanzania", 101.395F);<br />  }<br />}<br /><br />4.static nested class 和 inner class的不同?<br />nested class在c++中是嵌套类,inner class在java中是内部类.不同就是在于是否有指向外部的引用上.静态内部类意味着创建一个static内部类的对象,不需要一个外部类对象;不能从一个static内部类的一个对象访问到一个外部类的对象.<br /><br />5.&和&&的区别<br />&是位运算符,表示按位与运算;&&是逻辑运算符,表示逻辑与(and)<br /><br />6.Collection和Collections的区别<br />collection是集合类的上级接口,继承与它的接口主要是set和list<br />其中list必须以特定的顺序容纳元素;而一个set不能包含重复的元素.<br />映射(Map)一系列"键-值"对.可以返回自己键的一个set,一个包含自己值的list,或者包含自己(键-值)对的一个list.<br />均可构建自己的反复器.<br />collections类是针对集合类的一个帮助类.它提供一系列的静态方法对各种集合的搜索,排序,线程安全化等操作.<br /><br />public class SimpleCollection {<br />  public static void main(String[] args) {<br />    Collection c = new ArrayList();<br />    for(int i = 0; i &lt; 10; i++)<br />      c.add(Integer.toString(i));<br />    Iterator it = c.iterator();<br />    while(it.hasNext())<br />      System.out.println(it.next());<br />  }<br />}<br /><br />7.什么时候用assert<br />assertion(断言)在软件开发中是一种常用的调试方式，很多开发语言中都支持这种机制。在实现中，assertion就是在程序中的一条语句，它对一个boolean表达式进行检查，一个正确程序必须保证这个boolean表达式的值为true；如果该值为false，说明程序已经处于不正确的状态下，系统将给出警告或退出。一般来说，assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能，在软件发布后，assertion检查通常是关闭的.<br /><br />8.String s = new String("xyz");创建了几个String Object***<br />两个，一个字符对象，一个字符对象引用对象<br /><br />9.math.round(11.5)和math.round(-11.5)<br />前者等于12,后者等于-11.round方法返回与参数最接近的长整数.参数加0.5,求其floor<br /><br />10. short s1 = 1;s1 = s1+1;是否有错误? short s1 = 1;s1 += 1;是否有错误?<br />前者s1+1返回一个int型,需要强制类型转换.<br />后者正确.<br /><br />11.java种有没有goto?<br />有,为保留字.但是尚未使用.<br /><br />12.Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?<br />答：方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现，重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数，我们说该方法被重写 (Overriding)。子类的对象使用这个方法时，将调用子类中的定义，对它而言，父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法，它们或有不同的参数个数或有不同的参数类型，则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型<br /><br />13.Set里的元素是不能重复的，那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别<br />答：Set里的元素是不能重复的，那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等<br /> equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖，为的是当两个分离的对象的内容和类型相配的话，返回真值<br /><br />14.给我一个你最常见到的runtime exception?<br />答：常见的运行时异常有如下这些<br />ArithmeticException(异常的运算条件), <br />ArrayStoreException(向一个对象数组存放一错误类型的对象时)BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException..<br /><br />15.error和exception有什么区别?<br />答：error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况<br />    exception 表示一种设计或实现问题。也就是说，它表示如果程序运行正常，从不会发生的情况<br /><br />16.List, Set, Map是否继承自Collection接口<br />答： List，Set是，Map不是<br /><br />17.abstract class和interface的区别<br />答:声明方法的存在而不去实现它的类叫虚拟类(abstract class).它用于创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况.不能创建abstract class的实例.但是可以声明一个abstract class变量,将其指向其具体子类的一个实例.不能有抽象构造函数或抽象静态方法.Abstract 类的子类为它们父类中的所有抽象方法提供实现，否则它们也是抽象类为。取而代之，在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法.<br />接口（interface）是抽象类的变体。在接口中，所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的，没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似，除了该实现类不能从接口定义中继承行为。当类实现特殊接口时，它定义（即将程序体给予）所有这种接口的方法。然后，它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类，它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换，instanceof 运算符可以用来决定某对象的类是否实现了接口.<br />接口是一个更纯的抽象类.<br />18.接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)<br />答：接口可以继承接口。抽象类可以实现(implements)接口，抽象类可继承实体类，但前提是实体类必须有明确的构造函数<br /><br />19.abstract的method是否可同时是static,是否可同时是native，是否可同时是synchronized<br />答：都不能.其中synchronized:(同步.避免在你和别人同时访问一个属性的时候，属性的值发生不同步的问题.)<br />    native:(声明本地方法的关键字，可以通过声明的方法调用本地的动态链接库或者有C、C++等开发的函数。)<br /><br />20.构造器Constructor是否可被override(构造函数)<br />答：构造器Constructor不能被继承，因此不能重写Overriding，但可以被重载Overloading<br />1). 构造器不能是native,final,static,synchronized 的,可以是public,private,或什么都没有。<br />2). 构造器函数里可以写return呢,但后面什么都不许有(包括null)<br />3). 构造器不能返回值.<br />     但如果有个"构造器"返值了,它就不是构造器喽,只是个普通方法<br />4). super();this();这两个方法只能在构造方法里调用.<br />5). 成员变量声明时候赋值,比构造函数还早.<br /><br />21.是否可以继承String类<br />答：String类是final类故不可以继承<br /><br />22.try {}里有一个return语句，那么紧跟在这个try后的finally {}里的code会不会被执行，什么时候被执行，在return前还是后<br />答：会执行，在return前执行<br /><br />23.用最有效率的方法算出2乘以8等於几<br />答：2 &lt;&lt; 3<br /><br />24.两个对象值相同(x.equals(y) == true)，但却可有不同的hash code，这句话对不对<br />答：不对，有相同的hash code<br />在C++中，每个类多有地址。<br />java也一样，不过hash code不是地址，而是一个标识对象用的。（个人认为）<br />每个对象的hash code是不一样的，Object的默认hash code记得是按引用地址的。<br />对于String例外，是按String内容输出hash code的，这样可以用equals()来比较String的<br />内容是否相等了，而不是地址<br />在 Java 应用程序执行期间，在同一对象上多次调用 hashCode 方法时，必须一致地返回相同的整数，前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行，该整数无需保持一致。 <br />如果根据 equals(Object) 方法，两个对象是相等的，那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。 <br />以下情况不 是必需的：如果根据 equals(java.lang.Object) 方法，两个对象不相等，那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是，程序员应该知道，为不相等的对象生成不同整数结果可以提高哈希表的性能。 <br />实际上，由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。（这一般是通过将该对象的内部地址转换成一个整数来实现的，但是 JavaTM 编程语言不需要这种实现技巧。） <br /><br />25.当一个对象被当作参数传递到一个方法后，此方法可改变这个对象的属性，并可返回变化后的结果，那么这里到底是值传递还是引用传递<br />答：是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时，参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变，但对象的引用是永远不会改变的.<br /><br />26.swtich是否能作用在byte上，是否能作用在long上，是否能作用在String上<br />答：witch（expr1）中，expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich<br /><br />27.ArrayList和Vector的区别,HashMap和Hashtable的区别<br />答：就ArrayList与Vector主要从二方面来说.<br />一.同步性:Vector是线程安全的，也就是说是同步的，而ArrayList是线程序不安全的，不是同步的<br />二.数据增长:当需要增长时,Vector默认增长为原来一培，而ArrayList却是原来的一半<br />就HashMap与HashTable主要从三方面来说。<br />一.历史原因:Hashtable是基于陈旧的Dictionary类的，HashMap是Java 1.2引进的Map接口的一个实现<br />二.同步性:Hashtable是线程安全的，也就是说是同步的，而HashMap是线程序不安全的，不是同步的<br />三.值：只有HashMap可以让你将空值作为一个表的条目的key或value <br /><br />28.GC是什么? 为什么要有GC<br />答：GC是垃圾收集的意思（Gabage Collection）,内存处理是编程人员容易出现问题的地方，忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃，Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的，Java语言没有提供释放已分配内存的显示操作方法。<br /><br />29.float型float f=3.4是否正确?<br />答:不正确。精度不准确,应该用强制类型转换，如下所示：float f=(float)3.4<br /><br />30.介绍JAVA中的Collection FrameWork(包括如何写自己的数据结构)? <br />答：Collection FrameWork如下：<br />Collection<br />├List<br />│├LinkedList<br />│├ArrayList<br />│└Vector<br />│　└Stack<br />└Set<br />Map<br />├Hashtable<br />├HashMap<br />└WeakHashMap<br />Collection是最基本的集合接口，一个Collection代表一组Object，即Collection的元素（Elements）<br />Map提供key到value的映射.<br /><br />31.抽象类与接口？<br />答：抽象类与接口都用于抽象，但是抽象类(JAVA中)可以有自己的部分实现，而接口则完全是一个标识(同时有多重继承的功能) <br />JAVA类实现序例化的方法是实现java.io.Serializable接口<br />Collection框架中实现比较要实现Comparable 接口和 Comparator 接口<br /><br />32.STRING与STRINGBUFFER的区别。 <br />答：STRING的长度是不可变的，STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作，特别是内容要修改时，那么使用StringBuffer，如果最后需要String，那么使用StringBuffer的toString()方法<br /><br />33.谈谈final, finally, finalize的区别<br />答：final—修饰符（关键字）如果一个类被声明为final，意味着它不能再派生出新的子类，不能作为父类被继承。因此一个类不能既被声明为 abstract的，又被声明为final的。将变量或方法声明为final，可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值，而在以后的引用中只能读取，不可修改。被声明为final的方法也同样只能使用，不能重载<br />finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常，那么相匹配的 catch 子句就会执行，然后控制就会进入 finally 块（如果有的话）<br />finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的，因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的<br /><br />34.面向对象的特征有哪些方面 <br />答：主要有以下四方面：<br />1.抽象：<br />抽象就是忽略一个主题中与当前目标无关的那些方面，以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题，而只是选择其中的一部分，暂时不用部分细节。抽象包括两个方面，一是过程抽象，二是数据抽象。<br />2.继承：<br />继承是一种联结类的层次模型，并且允许和鼓励类的重用，它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生，这个过程称为类继承。新类继承了原始类的特性，新类称为原始类的派生类（子类），而原始类称为新类的基类（父类）。派生类可以从它的基类那里继承方法和实例变量，并且类可以修改或增加新的方法使之更适合特殊的需要。<br />3.封装：<br />封装是把过程和数据包围起来，对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念，即现实世界可以被描绘成一系列完全自治、封装的对象，这些对象通过一个受保护的接口访问其他对象。<br />4. 多态性：<br />多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势，很好的解决了应用程序函数同名问题。<br /><br />35.String是最基本的数据类型吗<br />答：基本数据类型包括byte、int、char、long、float、double、boolean和short。<br />java.lang.String类是final类型的，因此不可以继承这个类、不能修改这个类。为了提高效率节省空间，我们应该用StringBuffer类<br /><br />36.int 和 Integer 有什么区别<br />答：Java 提供两种不同的类型：引用类型和原始类型（或内置类型）。Int是java的原始数据类型，Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。原始类型封装类,booleanBoolean,charCharacter,byteByte,shortShort,intInteger,longLong,floatFloat,doubleDouble引用类型和原始类型的行为完全不同，并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法，它们包括：大小和速度问题，这种类型以哪种类型的数据结构存储，当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null，而原始类型实例变量的缺省值与它们的类型有关.<br /><br />37.运行时异常与一般异常有何异同<br />答：异常表示程序运行过程中可能出现的非正常状态，运行时异常表示虚拟机的通常操作中可能遇到的异常，是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常，但是并不要求必须声明抛出未被捕获的运行时异常。<br /><br />38.说出ArrayList,Vector, LinkedList的存储性能和特性<br />答：ArrayList和Vector都是使用数组方式存储数据，此数组元素数大于实际存储的数据以便增加和插入元素，它们都允许直接按序号索引元素，但是插入元素要涉及数组元素移动等内存操作，所以索引数据快而插入数据慢，Vector由于使用了synchronized方法（线程安全），通常性能上较ArrayList差，而LinkedList使用双向链表实现存储，按序号索引数据需要进行前向或后向遍历，但是插入数据时只需要记录本项的前后项即可，所以插入速度较快<br /><br />39.HashMap和Hashtable的区别<br />答：HashMap是Hashtable的轻量级实现（非线程安全的实现），他们都完成了Map接口，主要区别在于HashMap允许空（null）键值（key）,由于非线程安全，效率上可能高于Hashtable。<br />HashMap允许将null作为一个entry的key或者value，而Hashtable不允许。<br />HashMap把Hashtable的contains方法去掉了，改成containsvalue和containsKey。因为contains方法容易让人引起误解。 <br />Hashtable继承自Dictionary类，而HashMap是Java1.2引进的Map interface的一个实现。<br />最大的不同是，Hashtable的方法是Synchronize的，而HashMap不是，在多个线程访问Hashtable时，不需要自己为它的方法实现同步，而HashMap 就必须为之提供外同步。 <br />Hashtable和HashMap采用的hash/rehash算法都大概一样，所以性能不会有很大的差异。<br /><br />40.heap和stack有什么区别****<br />答：栈是一种线形集合，其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。堆是栈的一个组成元素<br /><br />41.Java中的异常处理机制的简单原理和应用<br />答：当JAVA程序违反了JAVA的语义规则时，JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAVA允许程序员扩展这种语义检查，程序员可以创建自己的异常，并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。<br /><br />42.垃圾回收的优点和原理。并考虑2种回收机制<br />答：Java语言中一个显著的特点就是引入了垃圾回收机制，使c++程序员最头疼的内存管理的问题迎刃而解，它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制，Java中的对象不再有"作用域"的概念，只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露，有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行，不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收，程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收，增量垃圾回收。<br /><br />43.你所知道的集合类都有哪些？主要方法？<br />答：最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector，它们是可变大小的列表，比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。 <br />Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对（称作"键"和"值"），其中每个键映射到一个值。<br /><br />44.描述一下JVM加载class文件的原理机制?<br />答：JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。<br /><br />45.排序都有哪几种方法？请列举<br />答：  排序的方法有：插入排序（直接插入排序、希尔排序），交换排序（冒泡排序、快速排序），选择排序（直接选择排序、堆排序），归并排序，分配排序（箱排序、基数排序）<br />快速排序的伪代码。<br />/ /使用快速排序方法对a[ 0 :n- 1 ]排序<br />从a[ 0 :n- 1 ]中选择一个元素作为m i d d l e，该元素为支点<br />把余下的元素分割为两段left 和r i g h t，使得l e f t中的元素都小于等于支点，而right 中的元素都大于等于支点<br />递归地使用快速排序方法对left 进行排序<br />递归地使用快速排序方法对right 进行排序<br />所得结果为l e f t + m i d d l e + r i g h t<br /><br />46.JAVA语言如何进行异常处理，关键字：throws,throw,try,catch,finally分别代表什么意义？在try块中可以抛出异常吗？<br />答：Java通过面向对象的方法进行异常处理，把各种不同的异常进行分类，并提供了良好的接口。在Java中，每个异常都是一个对象，它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象，该对象中包含有异常信息，调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的：try、catch、throw、throws和finally。一般情况下是用try来执行一段程序，如果出现异常，系统会抛出（throws）一个异常，这时候你可以通过它的类型来捕捉（catch）它，或最后（finally）由缺省处理器来处理。<br />用try来指定一块预防所有"异常"的程序。紧跟在try程序后面，应包含一个catch子句来指定你想要捕捉的"异常"的类型。<br />throw语句用来明确地抛出一个"异常"。<br />throws用来标明一个成员函数可能抛出的各种"异常"。<br />Finally为确保一段代码不管发生什么"异常"都被执行一段代码。<br />可以在一个成员函数调用的外面写一个try语句，在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句，"异常"的框架就放到堆栈上面，直到所有的try语句都完成。如果下一级的try语句没有对某种"异常"进行处理，堆栈就会展开，直到遇到有处理这种"异常"的try语句。<br /><br />47.一个".java"源文件中是否可以包括多个类（不是内部类）？有什么限制？<br />答：可以。必须只有一个类名与文件名相同。<br /><br />48.java中有几种类型的流？JDK为每种类型的流提供了一些抽象类以供继承，请说出他们分别是哪些类？<br />答：字节流，字符流。字节流继承于InputStream OutputStream，字符流继承于InputStreamReader OutputStreamWriter。在java.io包中还有许多其他的流，主要是为了提高性能和使用方便。<br /><br />49.java中会存在内存泄漏吗，请简单描述。<br />答：会。自己实现堆载的数据结构时有可能会出现内存泄露<br /><br />50.垃圾回收器的基本原理是什么？垃圾回收器可以马上回收内存吗？有什么办法主动通知虚拟机进行垃圾回收<br />答：对于GC来说，当程序员创建对象时，GC就开始监控这个对象的地址、大小以及使用情况。通常，GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的"，哪些对象是"不可达的"。当GC确定一些对象为"不可达"时，GC就有责任回收这些内存空间。可以。程序员可以手动执行System.gc()，通知GC运行，但是Java语言规范并不保证GC一定会执行。<br /><br />51.静态变量和实例变量的区别？<br />答：static i = 10; //常量   class A a;  a.i =10;//可变<br /><br />52.什么是java序列化，如何实现java序列化？*****<br />答：序列化就是一种用来处理对象流的机制，所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作，也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。<br />序列化的实现：将需要被序列化的类实现Serializable接口，该接口没有需要实现的方法，implements Serializable只是为了标注该对象是可被序列化的，然后使用一个输出流(如：FileOutputStream)来构造一个ObjectOutputStream(对象流)对象，接着，使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态)，要恢复的话则用输入流。<br /><br />53.是否可以从一个static方法内部发出对非static方法的调用？<br />答：不可以,如果其中包含对象的method()；不能保证对象初始化.<br /><br />54.写clone()方法时，通常都有一行代码，是什么？<br />答：Clone 有缺省行为，super.clone();他负责产生正确大小的空间，并逐位复制。<br /><br />55.在JAVA中，如何跳出当前的多重嵌套循环？<br />答：用break; return 方法。<br /><br />56.List、Map、Set三个接口，存取元素时，各有什么特点？<br />答：List 以特定次序来持有元素，可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value值，value可多值。<br /><br />57.说出一些常用的类，包，接口，请各举5个<br />答：常用的类：BufferedReader  BufferedWriter  FileReader  FileWirter  String  Integer<br />常用的包：java.lang  java.awt  java.io  java.util  java.sql<br />常用的接口：Remote  List  Map  Document  NodeList<br /><br />58.描述使用JDBC连接数据库的过程   <br />  Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");   <br />  String   url   =   "jdbc:obdc:mydb";   <br />  Connection   con   =   DriverManager.getConnection(url);   <br />  Statement   stmt   =   con.createStatement();   <br />  ResultSet   rs   =   stmt.execte("select   *   from   mytable");   <br /><br />59.什么是JNDI?   <br />  java命名目录接口<br /><br />60.Java 的通信编程，编程题(或问答)，用JAVA SOCKET编程，读服务器几个字符，再写入本地显示？ <br />答:Server端程序: <br />package test; <br />import java.net.*; <br />import java.io.*; <br /><br />public class Server <br />{ <br />private ServerSocket ss; <br />private Socket socket; <br />private BufferedReader in; <br />private PrintWriter out; <br />public Server() <br />{ <br />try <br />{ <br />ss=new ServerSocket(10000); <br />while(true) <br />{ <br />socket = ss.accept(); <br />String RemoteIP = socket.getInetAddress().getHostAddress(); <br />String RemotePort = ":"+socket.getLocalPort(); <br />System.out.println("A client come in!IP:"+RemoteIP+RemotePort); <br />in = new BufferedReader(new <br /><br />InputStreamReader(socket.getInputStream())); <br />String line = in.readLine(); <br />System.out.println("Cleint send is :" + line); <br />out = new PrintWriter(socket.getOutputStream(),true); <br />out.println("Your Message Received!"); <br />out.close(); <br />in.close(); <br />socket.close(); <br />} <br />}catch (IOException e) <br />{ <br />out.println("wrong"); <br />} <br />} <br />public static void main(String[] args) <br />{ <br />new Server(); <br />} <br />}; <br />Client端程序: <br />package test; <br />import java.io.*; <br />import java.net.*; <br /><br />public class Client <br />{ <br />Socket socket; <br />BufferedReader in; <br />PrintWriter out; <br />public Client() <br />{ <br />try <br />{ <br />System.out.println("Try to Connect to 127.0.0.1:10000"); <br />socket = new Socket("127.0.0.1",10000); <br />System.out.println("The Server Connected!"); <br />System.out.println("Please enter some Character:"); <br />BufferedReader line = new BufferedReader(new <br /><br />InputStreamReader(System.in)); <br />out = new PrintWriter(socket.getOutputStream(),true); <br />out.println(line.readLine()); <br />in = new BufferedReader(new InputStreamReader(socket.getInputStream())); <br />System.out.println(in.readLine()); <br />out.close(); <br />in.close(); <br />socket.close(); <br />}catch(IOException e) <br />{ <br />out.println("Wrong"); <br />} <br />} <br />public static void main(String[] args) <br />{ <br />new Client(); <br />} <br />}; <br /><br />61. 线程的基本概念、线程的本状态以及状态之间的关系<br />•新建 (Born) : 新建的线程处于新建状态<br />•就绪 (Ready) : 在创建线程后，它将处于就绪状态，等待 start() 方法被调用<br />•运行 (Running) : 线程在开始执行时进入运行状态<br />•睡眠 (Sleeping) : 线程的执行可通过使用 sleep() 方法来暂时中止。在睡眠后，线程将进入就绪状态<br />•等待 (Waiting) : 如果调用了 wait() 方法，线程将处于等待状态。用于在两个或多个线程并发运行时。<br />•挂起 (Suspended) : 在临时停止或中断线程的执行时，线程就处于挂起状态。<br />•恢复 (Resume) : 在挂起的线程被恢复执行时，可以说它已被恢复。<br />•阻塞 (Blocked) – 在线程等待一个事件时（例如输入/输出操作），就称其处于阻塞状态。<br />•死亡 (Dead) – 在 run() 方法已完成执行或其 stop() 方法被调用之后，线程就处于死亡状态。 <br />串行化的注意事项以及如何实现串行化答：如果有循环引用是不可以串行化的。对象输出流的WriteObject方法和 对象输入流的ReadObect 方法 <br /><br />62.内部类要点?<br />静态内部类可以有静态成员，而非静态内部类则不能有静态成员。<br />静态内部类的非静态成员可以访问外部类的静态变量，而不可访问外部类的非静态变量。<br />非静态内部类的非静态成员可以访问外部类的非静态变量。<br /><br /><br />63.java中有几种方法可以实现一个线程？用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用？<br />答：有两种实现方法，分别是继承Thread类与实现Runnable接口<br />用synchronized关键字修饰同步方法<br />反对使用stop()，是因为它不安全。它会解除由线程获取的所有锁定，而且如果对象处于一种不连贯状态，那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候，目标线程会停下来，但却仍然持有在这之前获得的锁定。此时，其他任何线程都不能访问锁定的资源，除非被"挂起"的线程恢复运行。对任何线程来说，如果它们想恢复目标线程，同时又试图使用任何一个锁定的资源，就会造成死锁。所以不应该使用suspend()，而应在自己的Thread类中置入一个标志，指出线程应该活动还是挂起。若标志指出线程应该挂起，便用wait()命其进入等待状态。若标志指出线程应当恢复，则用一个notify()重新启动线程。<br /><br />64.sleep() 和 wait() 有什么区别? <br />答：sleep是线程类（Thread）的方法，导致此线程暂停执行指定时间，给执行机会给其他线程，但是监控状态依然保持，到时后会自动恢复。调用sleep不会释放对象锁。<br />wait是Object类的方法，对此对象调用wait方法导致本线程放弃对象锁，进入等待此对象的等待锁定池，只有针对此对象发出notify方法（或notifyAll）后本线程才进入对象锁定池准备获得对象锁进入运行状态。<br /><br />65.同步和异步有何异同，在什么情况下分别使用他们？举例说明。<br />答：如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到，或者正在读的数据可能已经被另一个线程写过了，那么这些数据就是共享数据，必须进行同步存取。<br />当应用程序在对象上调用了一个需要花费很长时间来执行的方法，并且不希望让程序等待方法的返回时，就应该使用异步编程，在很多情况下采用异步途径往往更有效率。<br /><br />66.启动一个线程是用run()还是start()?<br />答：启动一个线程是调用start()方法，使线程所代表的虚拟处理机处于可运行状态，这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。<br /><br />67.当一个线程进入一个对象的一个synchronized方法后，其它线程是否可进入此对象的其它方法?<br />答：不能，一个对象的一个synchronized方法只能由一个线程访问。<br /><br />68.请说出你所知道的线程同步的方法。<br />答：wait():使一个线程处于等待状态，并且释放所持有的对象的lock。<br />sleep():使一个正在运行的线程处于睡眠状态，是一个静态方法，调用此方法要捕捉InterruptedException异常。<br />notify():唤醒一个处于等待状态的线程，注意的是在调用此方法的时候，并不能确切的唤醒某一个等待状态的线程，而是由JVM确定唤醒哪个线程，而且不是按优先级。<br />Allnotity():唤醒所有处入等待状态的线程，注意并不是给所有唤醒线程一个对象的锁，而是让它们竞争。<br /><br />69.多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? <br />答：多线程有两种实现方法，分别是继承Thread类与实现Runnable接口 <br />同步的实现方面有两种，分别是synchronized,wait与notify<br /><br />70.线程的基本概念、线程的基本状态以及状态之间的关系<br />答：线程指在程序执行过程中，能够执行程序代码的一个执行单位，每个程序至少都有一个线程，也就是程序本身。<br />Java中的线程有四种状态分别是：运行、就绪、挂起、结束<br /><br />71.简述synchronized和java.util.concurrent.locks.Lock的异同 ？<br />答：主要相同点：Lock能完成synchronized所实现的所有功能<br />主要不同点：Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁，而Lock一定要求程序员手工释放，并且必须在finally从句中释放。<br /><br /> <br /><br /> <br /><br /> <br /><br /><br /><br /><br /><br /><br /><br />jsp笔试<br /><br />1.jsp有哪些内置对象?作用分别是什么?<br />答：JSP共有以下9种基本内置组件（可与ASP的6种内部组件相对应）： <br />　request 用户端请求，此请求会包含来自GET/POST请求的参数 <br />   response 网页传回用户端的回应 <br />   pageContext 网页的属性是在这里管理 <br />   session 与请求有关的会话期 <br />   application servlet 正在执行的内容 <br />   out 用来传送回应的输出<br />   config servlet的构架部件 <br />   page JSP网页本身 <br />   exception 针对错误网页，未捕捉的例外 <br /><br />2.jsp有哪些动作?作用分别是什么?<br />答:JSP共有以下6种基本动作<br />   jsp:include：在页面被请求的时候引入一个文件。 <br />   jsp:useBean：寻找或者实例化一个JavaBean。 <br />   jsp:setProperty：设置JavaBean的属性。 <br />   jsp:getProperty：输出某个JavaBean的属性。 <br />   jsp:forward：把请求转到一个新的页面。 <br />   jsp:plugin：根据浏览器类型为Java插件生成OBJECT或EMBED标记<br /><br />3.forward 和redirect的区别<br />答：forward是服务器请求资源，服务器直接访问目标地址的URL，把那个URL的响应内容读取过来，然后把这些内容再发给浏览器，浏览器根本不知道服务器发送的内容是从哪儿来的，所以它的地址栏中还是原来的地址。<br />    redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址，一般来说浏览器会用刚才请求的所有参数重新请求，所以session,request参数都可以获取。<br /><br />4.JSP中动态INCLUDE与静态INCLUDE的区别？ <br />答：动态INCLUDE用jsp:include动作实现<br />   &lt;jsp:include page="included.jsp" flush="true" />它总是会检查所含文件中的变化，适合用于包含动态页面，并且可以带参数<br />   静态INCLUDE用include伪码实现,定不会检查所含文件的变化，适用于包含静态页面<br />   &lt;%@ include file="included.htm" %><br /><br />5.两种跳转方式分别是什么?有什么区别?<br />答：有两种，分别为：<br />  &lt;jsp:include page="included.jsp" flush="true"><br />  &lt;jsp:forward page= "nextpage.jsp"/><br />前者页面不会转向include所指的页面，只是显示该页的结果，主页面还是原来的页面。执行完后还会回来，相当于函数调用。并且可以带参数.后者完全转向新页面，不会再回来。相当于go to 语句。<br /><br />6.JSP的内置对象及方法。<br />答：request表示HttpServletRequest对象。它包含了有关浏览器请求的信息，并且提供了几个用于获取cookie, header, 和session数据的有用的方法。 <br />    response表示HttpServletResponse对象，并提供了几个用于设置送回 浏览器的响应的方法（如cookies,头信息等） <br />    out对象是javax.jsp.JspWriter的一个实例，并提供了几个方法使你能用于向浏览器回送输出结果。 <br />    pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API，并且包装了通用的servlet相关功能的方法。 <br />    session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息 <br />    applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息 <br />    config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。 <br />    page表示从该页面产生的一个servlet实例
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/153734#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, 07 Jan 2008 18:13:39 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/153734</link>
        <guid>http://piaochunzhi.javaeye.com/blog/153734</guid>
      </item>
      <item>
        <title>java中文件操作大全 </title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/153733" style="color:red;">http://piaochunzhi.javaeye.com/blog/153733</a>&nbsp;
          发表时间: 2008年01月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一.获得控制台用户输入的信息<br /><br /><pre name="code" class="java">
/** *//**获得控制台用户输入的信息
     * @return
     * @throws IOException
     */
    public String getInputMessage() throws IOException...{
        System.out.println("请输入您的命令∶");
        byte buffer[]=new byte[1024];
        int count=System.in.read(buffer);
        char[] ch=new char[count-2];//最后两位为结束符，删去不要
        for(int i=0;i&lt;count-2;i++)
            ch[i]=(char)buffer[i];
        String str=new String(ch);
        return str;
    }
</pre><br />可以返回用户输入的信息，不足之处在于不支持中文输入，有待进一步改进。<br /><br />二.复制文件<br /><br />1.以文件流的方式复制文件<br /><br /><pre name="code" class="java">
/** *//**以文件流的方式复制文件
     * @param src 文件源目录
     * @param dest 文件目的目录
     * @throws IOException  
     */
    public void copyFile(String src,String dest) throws IOException...{
        FileInputStream in=new FileInputStream(src);
        File file=new File(dest);
        if(!file.exists())
            file.createNewFile();
        FileOutputStream out=new FileOutputStream(file);
        int c;
        byte buffer[]=new byte[1024];
        while((c=in.read(buffer))!=-1)...{
            for(int i=0;i&lt;c;i++)
                out.write(buffer[i]);        
        }
        in.close();
        out.close();
    }
</pre><br />该方法经过测试，支持中文处理，并且可以复制多种类型，比如txt，xml，jpg，doc等多种格式<br /><br />三.写文件<br /><br />1.利用PrintStream写文件<br /><br /><pre name="code" class="java">
/** *//**
     * 文件输出示例
     */
    public void PrintStreamDemo()...{
        try ...{
            FileOutputStream out=new FileOutputStream("D:/test.txt");
            PrintStream p=new PrintStream(out);
            for(int i=0;i&lt;10;i++)
                p.println("This is "+i+" line");
        } catch (FileNotFoundException e) ...{
            e.printStackTrace();
        }
    }
</pre><br /><br /><br />2.利用StringBuffer写文件<br /><br /><pre name="code" class="java">
public void StringBufferDemo() throws IOException......{
        File file=new File("/root/sms.log");
        if(!file.exists())
            file.createNewFile();
        FileOutputStream out=new FileOutputStream(file,true);        
        for(int i=0;i&lt;10000;i++)......{
            StringBuffer sb=new StringBuffer();
            sb.append("这是第"+i+"行:前面介绍的各种方法都不关用,为什么总是奇怪的问题 ");
            out.write(sb.toString().getBytes("utf-8"));
        }        
        out.close();
    }
</pre><br /><br />该方法可以设定使用何种编码，有效解决中文问题。<br /><br />四.文件重命名<br /><br /><pre name="code" class="java">
    /** *//**文件重命名
     * @param path 文件目录
     * @param oldname  原来的文件名
     * @param newname 新文件名
     */
    public void renameFile(String path,String oldname,String newname)...{
        if(!oldname.equals(newname))...{//新的文件名和以前文件名不同时,才有必要进行重命名
            File oldfile=new File(path+"/"+oldname);
            File newfile=new File(path+"/"+newname);
            if(newfile.exists())//若在该目录下已经有一个文件和新文件名相同，则不允许重命名
                System.out.println(newname+"已经存在！");
            else...{
                oldfile.renameTo(newfile);
            } 
        }         
    }
</pre><br /><br /><br />五.转移文件目录<br /> <br /><br />转移文件目录不等同于复制文件，复制文件是复制后两个目录都存在该文件，而转移文件目录则是转移后，只有新目录中存在该文件。 <br /><pre name="code" class="java">
    /** *//**转移文件目录
     * @param filename 文件名
     * @param oldpath 旧目录
     * @param newpath 新目录
     * @param cover 若新目录下存在和转移文件具有相同文件名的文件时，是否覆盖新目录下文件，cover=true将会覆盖原文件，否则不操作
     */
    public void changeDirectory(String filename,String oldpath,String newpath,boolean cover)...{
        if(!oldpath.equals(newpath))...{
            File oldfile=new File(oldpath+"/"+filename);
            File newfile=new File(newpath+"/"+filename);
            if(newfile.exists())...{//若在待转移目录下，已经存在待转移文件
                if(cover)//覆盖
                    oldfile.renameTo(newfile);
                else
                    System.out.println("在新目录下已经存在："+filename);
            }
            else...{
                oldfile.renameTo(newfile);
            }
        }       
    }
</pre><br /> <br /><br />六.读文件<br /><br />1.利用FileInputStream读取文件<br /><pre name="code" class="java">

    /** *//**读文件
     * @param path
     * @return
     * @throws IOException
     */
    public String FileInputStreamDemo(String path) throws IOException...{
        File file=new File(path);
        if(!file.exists()||file.isDirectory())
            throw new FileNotFoundException();
        FileInputStream fis=new FileInputStream(file);
        byte[] buf = new byte[1024];
        StringBuffer sb=new StringBuffer();
        while((fis.read(buf))!=-1)...{
            sb.append(new String(buf));    
            buf=new byte[1024];//重新生成，避免和上次读取的数据重复
        }
        return sb.toString();
    }
</pre><br /><br />2.利用BufferedReader读取<br /><br />在IO操作，利用BufferedReader和BufferedWriter效率会更高一点<br /><pre name="code" class="java">
    /** *//**读文件
     * @param path
     * @return
     * @throws IOException
     */
    public String BufferedReaderDemo(String path) throws IOException...{
        File file=new File(path);
        if(!file.exists()||file.isDirectory())
            throw new FileNotFoundException();
        BufferedReader br=new BufferedReader(new FileReader(file));
        String temp=null;
        StringBuffer sb=new StringBuffer();
        temp=br.readLine();
        while(temp!=null)...{
            sb.append(temp+" ");
            temp=br.readLine();
        }
        return sb.toString();
    }
</pre><br /><br /><br />3.利用dom4j读取xml文件 <br /><pre name="code" class="java">
    /** *//**从目录中读取xml文件
     * @param path 文件目录
     * @return
     * @throws DocumentException
     * @throws IOException
     */
    public Document readXml(String path) throws DocumentException, IOException...{
        File file=new File(path);
        BufferedReader bufferedreader = new BufferedReader(new FileReader(file));
        SAXReader saxreader = new SAXReader();
        Document document = (Document)saxreader.read(bufferedreader);
        bufferedreader.close();
        return document;
    }
 </pre><br /><br /><br /><br />七.创建文件(文件夹)<br /><pre name="code" class="java">
1.创建文件夹 /** *//**创建文件夹
     * @param path  目录
     */
    public void createDir(String path)...{
        File dir=new File(path);
        if(!dir.exists())
            dir.mkdir();
    }
</pre><br /><br /><br />2.创建新文件/** *//**创建新文件<br /><pre name="code" class="java">
     * @param path 目录
     * @param filename 文件名
     * @throws IOException
     */
    public void createFile(String path,String filename) throws IOException...{
        File file=new File(path+"/"+filename);
        if(!file.exists())
            file.createNewFile();
    }
</pre><br /><br /><br />八.删除文件(目录)<br />1.删除文件    <br /><pre name="code" class="java">
/** *//**删除文件

     * @param path 目录
     * @param filename 文件名
     */
    public void delFile(String path,String filename)...{
        File file=new File(path+"/"+filename);
        if(file.exists()&&file.isFile())
            file.delete();
    }
</pre><br /><br />2.删除目录<br />要利用File类的delete()方法删除目录时，必须保证该目录下没有文件或者子目录，否则删除失败，因此在实际应用中，我们要删除目录，必须利用递归删除该目录下的所有子目录和文件，然后再删除该目录。 /** *//**递归删除文件夹<br /><pre name="code" class="java">
     * @param path
     */
    public void delDir(String path)...{
        File dir=new File(path);
        if(dir.exists())...{
            File[] tmp=dir.listFiles();
            for(int i=0;i&lt;tmp.length;i++)...{
                if(tmp[i].isDirectory())...{
                    delDir(path+"/"+tmp[i].getName());
                }
                else...{
                    tmp[i].delete();
                }
            }
            dir.delete();
        }
    } 
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/153733#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, 07 Jan 2008 18:08:13 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/153733</link>
        <guid>http://piaochunzhi.javaeye.com/blog/153733</guid>
      </item>
      <item>
        <title>Log4j文档</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/153732" style="color:red;">http://piaochunzhi.javaeye.com/blog/153732</a>&nbsp;
          发表时间: 2008年01月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Log4j文档<br /><br /> <br /><br />Log4j由三个重要的组件构成：日志信息的优先级，日志信息的输出目的地，日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、INFO、DEBUG，分别用来指定这条日志信息的重要程度；日志信息的输出目的地指定了日志将打印到控制台还是文件中；而输出格式则控制了日志信息的显示内容。<br /><br /> <br /><br />一、       定义配置文件<br /><br />  Log4j支持两种配置文件格式，一种是Java特性文件(properties格式的属性文件)，一种是XML格式的文件。<br /><br /> <br /><br />1.    以Java特性文件(properties格式的属性文件)做为配置文件<br /><br />  Java特性文件也位于WEB-INF/classes目录下，下面是一个Java特性文件(properties格式的属性文件)的例子：<br /><br /> <br /><br /> <br /><br /><pre name="code" class="java">
# For JBoss: Avoid to setup log4j outside $JBOSS_HOME/server/default/deploy/log4j.xml

# For all other servers: Comment out the Log4J listener in web.xml too

 

log4j.configuration=log4j.properties

 

log4j.rootCategory=info, stdout, logfile

 

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - &lt;%m>%n

 

log4j.appender.logfile=org.apache.log4j.RollingFileAppender

log4j.appender.logfile.File=D:/temp/SpringMVC.log

log4j.appender.logfile.MaxFileSize=512KB

# Keep three backup files

log4j.appender.logfile.MaxBackupIndex=3

log4j.appender.logfile.layout=org.apache.log4j.PatternLayout

# Pattern to output: date priority [category] - &lt;message>line_separator

log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - &lt;%m>%n

 

#log4j.logger.com.opensymphony.oscache=ERROR

#log4j.logger.net.sf.navigator=ERROR

#log4j.logger.org.apache.commons=ERROR

#log4j.logger.org.apache.struts=WARN

#log4j.logger.org.displaytag=ERROR

log4j.logger.org.springframework=WARN

#log4j.logger.com.ibatis.db=WARN
 
</pre><br /><br /><br /> <br /><br />  当Tomcat服务器启动时自动加载.properties配置文件。<br /><br />其中，<br /><br />log4j.configuration=log4j.properties 是指定配置文件的名字。<br /><br />log4j.rootCategory= [ level ] , appenderName, appenderName, … 是配置根Logger。<br /><br /><br />level 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别，优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别，则应用程序中所有DEBUG级别的日志信息将不被打印出来，默认日志级别是ERROR；appenderName就是指定Appender组件，确定日志输出目的地。如上例：log4j.rootCategory=info, stdout, logfile 配置根Logger的级别是INFO，日志输出的目的地是stdout, logfile。<br /> <br /><br /> <br /><br />    log4j.appender. appenderName =org.apache.log4j.ConsoleAppender是配置日志信息输出目的地Appender。<br /><br /><br /> Log4j提供的appender有以下几种： <br />　　org.apache.log4j.ConsoleAppender（控制台）， <br />　　org.apache.log4j.FileAppender（文件）， <br />　　org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br />　　org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）， <br />　　org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br /> <br /><br /> <br /><br />   log4j.appender.appenderName.layout=org.apache.log4j.PatternLayout 配置日志信息的格式（布局）<br /><br /><br />   Log4j提供的layout有以下几种： <br />　　org.apache.log4j.HTMLLayout（以HTML表格形式布局）， <br />　　org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， <br />　　org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， <br />　　org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br /> <br /><br /> <br /><br />   log4j.appender. appenderName.layout.ConversionPattern=%d %p [%c] - &lt;%m>%n  是设置打印格式格式化日志信息。<br /><br /><br />打印参数如下： <br /><br />%m 输出代码中指定的消息<br /><br />%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL <br />%r 输出自应用启动到输出该log信息耗费的毫秒数 <br />%c 输出所属的类目，通常就是所在类的全名 <br />%t 输出产生该日志事件的线程名 <br />%n 输出一个回车换行符，Windows平台为“\r\n”，Unix平台为“\n” <br />%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921 <br />%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。举例：Testlog4.main(TestLog4.java:10) <br /> <br /><br /> <br /><br />  如果log4j.appender. appenderName 属性配置的日志输出目的地是一个文件是，还有以下属性：<br /><br /><br />    log4j.appender. appenderName.File=D:/temp/SpringMVC.log  配置日志文件的名称。即存放日志的文件。<br /><br />    log4j.appender. appenderName.MaxFileSize=512KB  配置日志文件的大小，最大可以设置为10M。<br /><br />    log4j.appender. appenderName.MaxBackupIndex=3  配置可有日志文件的个数。<br /> <br /><br /> <br /><br />  Log4j.logger&lt;.logger.name>= level  指定Logger.name这个记录器的级别。即，logger只输出这个级别或高出这个级别的日志。如：  <br /><br /><br />log4j.logger.org.springframework=WARN  是配置Logger只输出关于org.springframework的WARN级别的日志和ERROR和FATAL级别的日志。<br /><br />    log4j.logger.org.displaytag=ERROR  是配置Logger只输出关于displaytag的ERROR 和FATAL级别的日志。<br /> <br /><br /> <br /><br />  如果将日志以邮件的形式发送出去时得有以下属性: <br /><br /><br />log4j.appender.mail=org.apache.log4j.net.SMTPAppender  配置日志输出目的地是电子邮箱<br /><br />log4j.appender.mail.To= lmbussiness@hotmail.com        设置日志将要输出到的电子邮箱<br /><br />log4j.appender.mail.From=localhost@raibledesignes.com  设置发送日志信息的电子邮箱<br /><br />log4j.appender.mail.SMTPHost=localhost             设置运行SMTP守护程序的主机的IP地址名称<br /><br />log4j.appender.mail.Threshold=ERROR                设置记录日志的最低级别<br /><br />log4j.appender.mail.BufferSize=1                   设置写邮件的缓存大小<br /><br />log4j.appender.mail.Subject=[localhost]dlhitech Application Error  设置电子邮件标题<br /> <br /><br />     如果将日志输出到数据库日志表时有以下属性:<br /><br /><br />log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender    配置日志输出目的地是数据库<br />log4j.appender.DATABASE.URL=jdbc:oracle:thin:@192.168.1.10:1521:SCSORA   配置连接数据库的url<br />log4j.appender.DATABASE.driver=oracle.jdbc.drivers.OracleDrivers        配置连接数据库的驱动器<br />log4j.appender.DATABASE.user=newsinfo                                  配置连接数据库的用户名<br />log4j.appender.DATABASE.password=newsinfo                             配置连接数据库的密码 <br />log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')                                    设置插入语句<br />log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout     配置日志信息的格式（布局）<br />log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n                                                       设置打印格式格式化日志信息。<br /> <br /><br /> <br /><br /> <br /><br />2.以XML格式的文件作为配置文件<br /><br />  下面是一个XML格式的文件作为配置文件的例子：<br /><br />   <br /><br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="UTF-8" ?>

&lt;!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

&lt;log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

        

   &lt;appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">

     &lt;param name="threshold" value="error"/>

     &lt;layout class="org.apache.log4j. PatternLayout">

       &lt;param name="Conversion" value="%d{(yyyy年MM月dd日-HH時mm分ss秒)} %p [%c] - &lt;%m>%n "/>
&lt;/layout>

   &lt;/appender>

   

   &lt;appender name="rollingFile.log" class="org.apache.log4j.RollingFileAppender">
     &lt;param name="File" value=" D:/temp/SpringMVC.log " />
&lt;param name="threshold" value="info"/>
     &lt;param name="Append" value="false" />
     &lt;param name="MaxBackupIndex" value="2" />
     &lt;param name="MaxFileSize" value="1024" />
     &lt;layout class="org.apache.log4j.PatternLayout" >
       &lt;param name=" ConversionPattern " value="%d [%t] %p - %m%n" />
     &lt;/layout>
    &lt;!-- 实现过滤功能，用这个标签，当往这个指定文件记录日志时只记录指定级别的日志，别的不记录 。
Filter标签只能在xml配置文件好用，在.properties属性文件中不好用-->
&lt;filter class="org.apache.log4j.varia.LevelRangeFilter">
      &lt;param name="LevelMin"      value="ERROR"/>
      &lt;param name="LevelMax"      value="ERROR"/>
      &lt;param name="acceptOnMatch" value="TRUE"/>
    &lt;/filter>
   &lt;/appender>
&lt;!—封装apache ，这样，可以在java程序中的

Category cat2 = Category.getInstance("your.category.name"); 来进行输出日志-->

&lt;category name="org.apache">      --设置封装的名称

&lt;priority value="info" />     --输出指定级别的日志

&lt;appender-ref ref="aplog"/>   --设置输出的目的地

&lt;/category>

&lt;root>

     &lt;level value ="debug" />

     &lt;appender-ref ref="ConsoleAppender"/>

&lt;appender-ref ref=" rollingFile.log "/>  &lt;!--  经过过滤只记录error级别的日志  -->

   &lt;/root>

&lt;/log4j:configuration>
 
</pre><br /> <br /><br /> <br /><br />二．调用Log4j来输出日志<br /><br />  通过访问通用日志接口和在java程序手动打开配置文件都可以进行日志的输出。其中，通过访问通用日志接口来指定日志器时，Log4j的配置文件只能是java特定文件(.properties属性文件)。<br /><br /> <br /><br />1.通过访问通用日志接口来输出日志<br /><br />  当Tomcat服务器启动时，通用日志接口从名为“commons-logging.properties”的属性文件中获取实现日志接口日志器信息，这个文件位于WEB-INF/classes目录下。“commons-logging.properties”属性文件的内容：<br /><br />  <br /><br /><br /> <br /><br />org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JCategoryLog<br /><br /> <br /> <br /><br />  当Tomcat服务器运行时，通用日志接口会检索commons-logging.properties文件，并且实例化由“org.apache.commons.logging.Log”属性指定的日志实现例。上面给的日志器是Log4J日志器。<br /><br />  Tomcat服务器会自动加载.properties配置文件。<br /><br />  调用Log4j输出日志 如下例：<br /><br /><pre name="code" class="java">
  import org.apache.commons.logging.Log;

   

public class Test{

      public static void main(args[] String){

    Log logger = LogFactory.getLog(“test”);

    logger.info("开始操作");

    int a = 5;

    int b = 6;

    System.out.println(a+b);

    logger.info("操作完毕");

}

}
 
</pre><br /> <br /><br />2.手动打开配置文件输出日志<br /><br />  程序员用手动打开配置文件来输出日志时，得先打开配置文件然后才能进行输出日志操作。由于Log4J的配置文件可以是java特性文件(.properties属性文件)和.xml文件，所以打开配置文件的方式就不相同。当配置文件是java特性文件(.properties属性文件)时，打开配置文件的方法是：<br /><br /><br /> <br /><pre name="code" class="java">
PropertyConfigurator.configure ( String configFilename);
</pre><br /> <br /> <br /><br />当配置文件是.xml文件时，打开配置文件的方法是：<br /><br /><br /> <br /><pre name="code" class="java">
DOMConfigurator.configure ( String filename );
</pre><br /> <br /> <br /><br />当打开配置文件后，配置文件就一直打开着，所以配置文件就打开一遍就可以了。<br /><br />  打开配置文件后，构造Logger对象然后输出日志信息，以配置文件是.xml文件为例，输出信息实例如下：<br /><br /><br /> <br /><pre name="code" class="java">
import org.apache.log4j.Logger;

import org.apache.log4j.xml.DOMConfigurator;   

public class Test{

      public static void main(args[] String){

          DOMConfigurator.configure ( String filename )；

          Logger logger = Logger.getRootLogger();

          logger.info("开始操作");

          int a = 5;

          int b = 6;

         System.out.println(a+b);

         logger.info("操作完毕");

}

}
 </pre><br /><br /> <br /><br />2.不通过配置文件手动输出日志<br /><br />  使用Log4J来输出日志不一定非得通过配置文件来输出日志，也可以不通过配置文件来输出日志，手动在程序中创建Appender、Layout等对象，只不过这样做会在java程序用留下很大的代码量。下面是一个不通过配置文件手动输出日志的实例，程序实现了PatternLayout和FileAppender：<br /><pre name="code" class="java">

     import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.apache.log4j.SimpleLayout;

import org.apache.log4j.FileAppender;

public class simpandfile {

         static Logger logger = Logger.getLogger(simpandfile.class);

         public static void main(String args[]) {

           String pattern =  "Milliseconds since program start: %r %n";

                   pattern += "Classname of caller: %C %n";

                   pattern += "Date in ISO8601 format: %d{ISO8601} %n";

                   pattern += "Location of log event: %l %n";

                   pattern += "Message: %m %n %n"; 

           PatternLayout layout = new PatternLayout(pattern);

           FileAppender appender = null;

             try {

                 appender = new FileAppender(layout,"output1.txt",false);

              } catch(Exception e) {}

              logger.addAppender(appender);

              logger.setLevel((Level) Level.DEBUG);

              logger.debug("Here is some DEBUG");

              logger.info("Here is some INFO");

              logger.warn("Here is some WARN");

              logger.error("Here is some ERROR");

              logger.fatal("Here is some FATAL");

        }

}
 </pre>
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/153732#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, 07 Jan 2008 18:02:50 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/153732</link>
        <guid>http://piaochunzhi.javaeye.com/blog/153732</guid>
      </item>
      <item>
        <title>JSON学习</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/153727" style="color:red;">http://piaochunzhi.javaeye.com/blog/153727</a>&nbsp;
          发表时间: 2008年01月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          JSON （JavaScript Object Notation）一种简单的数据格式，比xml更轻巧。 JSON 是 JavaScript 原生格式，这意味着在 JavaScript 中处理 JSON 数据不需要任何特殊的 API 或工具包。 JSON的规则很简单： 对象是一个无序的“‘名称/值’对”集合。一个对象以“{”（左括号）开始，“}”（右括号）结束。每个“名称”后跟一个“:”（冒号）；“‘名称/值’ 对”之间使用“,”（逗号）分隔。具体细节参考http://www.json.org/json-zh.html 举个简单的例子： js 代码<br /><br /><pre name="code" class="java">
function showJSON() {    
    var user =     
    {     
        "username":"andy",    
        "age":20,    
        "info": { "tel": "123456", "cellphone": "98765"},    
        "address":    
            [    
                {"city":"beijing","postcode":"222333"},    
                {"city":"newyork","postcode":"555666"}    
            ]    
    }    
        
    alert(user.username);    
    alert(user.age);    
    alert(user.info.cellphone);    
    alert(user.address[0].city);    
    alert(user.address[0].postcode);    
}    
</pre><br /><br />这表示一个user对象，拥有username, age, info, address 等属性。<br />同样也可以用JSON来简单的修改数据，修改上面的例子<br />js 代码<br /><br /><pre name="code" class="java">
function showJSON() {    
    var user =     
    {     
        "username":"andy",    
        "age":20,    
        "info": { "tel": "123456", "cellphone": "98765"},    
        "address":    
            [    
                {"city":"beijing","postcode":"222333"},    
                {"city":"newyork","postcode":"555666"}    
            ]    
    }    
        
    alert(user.username);    
    alert(user.age);    
    alert(user.info.cellphone);    
    alert(user.address[0].city);    
    alert(user.address[0].postcode);    
        
    user.username = "Tom";    
    alert(user.username);    
}    
</pre><br /><br /><br /> JSON提供了json.js包，下载http://www.json.org/json.js 后，将其引入然后就可以简单的使用object.toJSONString()转换成JSON数据。<br />js 代码<br /><br /><pre name="code" class="java">
function showCar() {    
    var carr = new Car("Dodge", "Coronet R/T", 1968, "yellow");    
    alert(carr.toJSONString());    
}    
   
function Car(make, model, year, color)       {    
     this.make  =  make;    
     this.model  =  model;    
     this.year  =  year;    
     this.color  =  color;    
}    
</pre><br /><br /><br />可以使用eval来转换JSON字符到Object<br />js 代码<br /><br /><pre name="code" class="java">
function myEval() {    
    var str = '{ "name": "Violet", "occupation": "character" }';    
    var obj = eval('(' + str + ')');    
    alert(obj.toJSONString());    
}    
</pre><br /><br />或者使用parseJSON()方法<br />js 代码<br /><br /><pre name="code" class="java">
function myEval() {    
    var str = '{ "name": "Violet", "occupation": "character" }';    
    var obj = str.parseJSON();    
    alert(obj.toJSONString());    
}    
</pre><br /><br /><br />下面使用prototype写一个JSON的ajax例子。<br />先写一个servlet (我的是servlet.ajax.JSONTest1.java)就写一句话 <br />java 代码<br /><pre name="code" class="java">
response.getWriter().print("{ \"name\": \"Violet\", \"occupation\": \"character\" }");  
</pre><br /> <br />再在页面中写一个ajax的请求<br />js 代码<br /><pre name="code" class="java">
function sendRequest() {    
    var url = "/MyWebApp/JSONTest1";    
    var mailAjax = new Ajax.Request(    
        url,    
        {    
            method: 'get',    
            onComplete: jsonResponse    
        }    
    );    
}    
   
function jsonResponse(originalRequest) {    
    alert(originalRequest.responseText);    
    var myobj = originalRequest.responseText.parseJSON();    
    alert(myobj.name);    
}    
</pre><br /><br /><br />prototype-1.5.1.js中提供了JSON的方法，String.evalJSON(), 可以不使用json.js, 修改上面的方法<br />js 代码<br /><br /><pre name="code" class="java">
function jsonResponse(originalRequest) {    
    alert(originalRequest.responseText);    
    var myobj = originalRequest.responseText.evalJSON(true);    
    alert(myobj.name);    
}    
</pre><br /><br /><br />JSON还提供了java的jar包 http://www.json.org/java/index.html API也很简单，下面举个例子<br />在javascript中填加请求参数<br />js 代码<br /><br /><pre name="code" class="java">
function sendRequest() {    
    var carr = new Car("Dodge", "Coronet R/T", 1968, "yellow");    
    var pars = "car=" + carr.toJSONString();    
   
    var url = "/MyWebApp/JSONTest1";    
    var mailAjax = new Ajax.Request(    
        url,    
        {    
            method: 'get',    
            parameters: pars,    
            onComplete: jsonResponse    
        }    
    );    
}    
</pre><br /><br /><br />使用JSON请求字符串就可以简单的生成JSONObject并进行解析,修改servlet添加JSON的处理(要使用json.jar)<br />java 代码<br /><pre name="code" class="java">
private void doService(HttpServletRequest request, HttpServletResponse response) throws IOException {    
        String s3 = request.getParameter("car");    
        try {    
            JSONObject jsonObj = new JSONObject(s3);    
            System.out.println(jsonObj.getString("model"));    
            System.out.println(jsonObj.getInt("year"));    
        } catch (JSONException e) {    
            e.printStackTrace();    
        }    
        response.getWriter().print("{ \"name\": \"Violet\", \"occupation\": \"character\" }");    
    }   
</pre><br /> <br />同样可以使用JSONObject生成JSON字符串，修改servlet<br />java 代码<br /><br /><pre name="code" class="java">
private void doService(HttpServletRequest request, HttpServletResponse response) throws IOException {    
        String s3 = request.getParameter("car");    
        try {    
            JSONObject jsonObj = new JSONObject(s3);    
            System.out.println(jsonObj.getString("model"));    
            System.out.println(jsonObj.getInt("year"));    
        } catch (JSONException e) {    
            e.printStackTrace();    
        }    
            
        JSONObject resultJSON = new JSONObject();    
        try {    
            resultJSON.append("name", "Violet")    
                      .append("occupation", "developer")    
                      .append("age", new Integer(22));    
            System.out.println(resultJSON.toString());    
        } catch (JSONException e) {    
            e.printStackTrace();    
        }    
        response.getWriter().print(resultJSON.toString());    
    }    
</pre><br /><br /><br />js 代码<br /><br /><pre name="code" class="java">
function jsonResponse(originalRequest) {    
    alert(originalRequest.responseText);    
    var myobj = originalRequest.responseText.evalJSON(true);    
    alert(myobj.name);    
    alert(myobj.age);    
}   
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/153727#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, 07 Jan 2008 17:56:27 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/153727</link>
        <guid>http://piaochunzhi.javaeye.com/blog/153727</guid>
      </item>
      <item>
        <title>计划任务工具 cron 的配置和说明</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/153724" style="color:red;">http://piaochunzhi.javaeye.com/blog/153724</a>&nbsp;
          发表时间: 2008年01月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          计划任务工具 cron 的配置和说明2007-01-24 11:151、计划任务概说；<br /><br />计划任务，是任务在约定的时间执行已经计划好的工作，这是表面的意思。在Linux中，我们经常用到 crond 服务器来完成这项工作。cron服务器可以根据配置文件约定的时间来执行特定的作务。比如我们可以在配置文件中约定每天早上4点，对httpd 服务器重新启动，这就是一个计划任务；<br /><br />下面我们先来说说cron；<br /><br /><br />2、cron；<br /><br /><br />在Linux系统中，计划任务一般是由cron承担，我们可以把cron设置为开机时自动启动。cron启动后，它会读取它的所有配置文件（全局性配置文件/etc/crontab，以及每个用户的计划任务配置文件），然后cron会根据命令和执行时间来按时来调用度工作任务。<br /><br /><br />2.1 cron 的安装和启动；<br /><br /><br />在一般情况下，cron都是系统默认安装的，我们要学会查看软件包是否已经安装；<br /><br /><br />2.1.1 在Redhat 或 Fedora等RPM包管理的系统的安装；<br /><br /><br />判断系统是否已经安装cron相关的包 <br /><br />Fedora 5.0 系统的情况；<br /><br />其它版本的Fedora及Redhat的系统和这相似；<br /><br /><br />[root@localhost ~]# rpm -qa |grep cron<br />vixie-cron-4.1-54.FC5<br />anacron-2.3-36.1<br />crontabs-1.10-7.1<br /><br />其中vixie-cron软件包是cron的主程序，您可以通过下面的命令来了解它，其它软件包同理；<br /><br /><br />[root@localhost beinan]# rpm -ql vixie-cron<br /><br />crontabs 软件包是用来安装、卸装、或列举用来驱动 cron 守护进程的表格的程序。cron 守护进程检查 crontab 文件来查看某个指定命令被调度执行的时间。如果命令已经调度，守护进程就会执行它们。了解crontabs软件包都安装了些什么，应该用下面的命令；<br /><br /><br />[root@localhost beinan]# rpm -ql crontabs<br /><br />如果没有安装，可以从光盘中找出文件名带有cron字样的软件包来安装。<br /><br /><br />[root@localhost ~]# rpm -ivh vixie-cron-4.1-54.FC5*<br />[root@localhost ~]# rpm -ivh crontabs*<br /><br />也可以用yum 来在线安装；<br /><br /><br />[root@localhost ~]# yum install vixie-cron<br />[root@localhost ~]# yum install crontabs<br /><br /><br />2.1.2 在Slackware系统中的安装；<br /><br /><br />在Slackware中cron软件包是 dcron，您可以在光盘中找出来安装它；<br /><br />查看是否已经安装了dcron软件包，您可以这样查看。在这里能列出软件包详细的安装情况；<br /><br /><br />[root@localhost ~]# more /var/adm/packages/dcron*<br /><br />如果没有安装，请用下面的命令来安装。在第一张安装盘中找出dcron软件包；<br /><br /><br />[root@localhost ~]# installpkg dcron*.tgz<br /><br /><br />2.1.3 cron 的开启、停止、重新启动方法；<br /><br /><br />cron配置文件被修改后，想让新文件生效，必须重新crond服务器，有两种方法可供选择；<br /><br /><br />第一种 在Fedora或Redhat 等以RPM包管理的系统中；<br /><br /> <br /><br />[root@localhost ~]# /etc/init.d/crond start<br />[root@localhost ~]# /etc/init.d/crond stop<br />[root@localhost ~]# /etc/init.d/crond restart<br /><br />如果想在Fedora 和 Redhat 或以这些发行版为基础克隆的发行版，如果想自动开机运行，请用下面的办法；<br /><br /><br />[root@localhost ~]# chkconfig --levels 35 crond on<br /><br />第二种：通用<br /><br /><br />[root@localhost ~]# pgrep crond 注：判断crond 是否在运行；<br />[root@localhost ~]# pkill crond 注：杀掉正在运行中的crond；<br />[root@localhost ~]# pgrep crond 注：查看是否被杀掉了；<br />[root@localhost ~]# /usr/sbin/crond 注：运行crond；<br /><br /><br />2.2 cron 配置文件；<br /><br /><br />cron 是一个服务器程序，我们都知道Linux的服务器的配置，大多是通过配置文件来完成的，cron自然也不例外，在Redhat/Fedora 等系统中它的全局性配置文件是/etc/crontab；在Slackware系统中，全局性文件是/var/spool/cron/crontabs/root 。每个用户也有自己的cron配置文件，我们可以通过crontab -e 来编辑它；<br /><br /><br />2.2.1 全局性配置文件；<br /><br /><br />下面是一个全局性的配置文件例子，以Fedora Core 5为例；<br /><br /><br />[root@localhost ~]# more /etc/crontab<br />SHELL=/bin/bash<br />PATH=/sbin:/bin:/usr/sbin:/usr/bin<br />MAILTO=root<br />HOME=/<br /># run-parts<br />1 * * * * root run-parts /etc/cron.hourly<br />#<br />2 4 * * * root run-parts /etc/cron.daily<br />#<br />22 4 * * 7 root run-parts /etc/cron.weekly<br />#<br />42 4 1 * * root run-parts /etc/cron.monthly<br />#<br />0,5,10,15,20,25,30,35,40,45,50,55 * * * * root /usr/bin/mrtg /etc/mrtg/mrtg.cfg<br /><br />对于全局性配置文件，我们要用root权限来更改，一般是通过crontab -e 来修改。但有时也并不一定是这样的，比如Fedora Core 5 如果通过crontab -e 修改的是root用户的cron 配置文件。所以我们要在Fedora Core 5中修改全局性配置文件可以用vi 编辑器来修改。vi的用法请参考：《文件编辑器 vi》<br /><br />在全局性配置文件中，定义了可执行命令的路径环境变量，所用SHELL类型的定义等，这些大多不用修改；我们经常添加的是计划任务或修改任务执行的时间等；<br /><br />在全局性配置文件中，我们发现有类似这些行；<br /><br /><br />1 * * * * root run-parts /etc/cron.hourly 注：表示每个小时的第一分钟，开始执行/etc/hourly目录下的可执行程序或脚本；<br />2 4 * * * root run-parts /etc/cron.daily 注：表示每天的4点2分，开始执行/etc/cron.daily目录下的可执行程序或脚本；<br />22 4 * * 7 root run-parts /etc/cron.weekly 注：每年第7个周4点我22分，开始执行 /etc/cron.weekly目录下的可执行程序或脚本；<br />42 4 1 * * root run-parts /etc/cron.monthly 注：每月第1天的4点42分，开始执行/etc/cron.monthly目录下的可执行程序或脚本；<br /><br />这些行是用来在同一时间批量执行任务的，我们在以后的例子中独立出来解说，在这里只是让大家心中有数；<br /><br /><br />2.2.2 cron 配置计划任务的书写格式<br /><br /> <br /><br />分钟 小时 日 月 周 ［用户名］ 命令<br /><br />说明：<br /><br />第一段应该定义的是：分钟，表示每个小时的第几分钟来执行。范围是从0-59<br />第二段应该定义的是：小时，表示从第几个小时来执行，范围是从0-23<br />第三段应该定义的是：日期，表示从每个月的第几天执行，范围从1-31<br />第四段应该定义的是：月，表示每年的第几个月来执行，范围从1-12<br />第五段应该定义的是：周，表示每周的第几天执行，范围从0-6，其中 0表示星期日。<br />每六段应该定义的是：用户名，也就是执行程序要通过哪个用户来执行，这个一般可以省略；<br />第七段应该定义的是：执行的命令和参数。<br />注：其中用户名可是省略，用户名定义的是程序用哪个用户来执行，比如mysql服务器，我们可以定义成以mysql用户来启动、停止、重新启动，这时要写上用户名；不过对于cron来说意义不是太大，因为每个用户都有自己的cron配置文件。有些程序的启动必须用到root用户，这时我们就可以修改root用户的cron配置文件就行了。在每个用户的配置文件中，不必指定用户名。<br /><br />我们可以把计划任务写在全局性配置文件中，如果您想把一个计划放入全局性配置文件中，就得改发行版所对应的cron全局配置文件，比如Fedora 5的全局性配置文件是/etc/crontab文件；<br /><br />每个用户也能定义自己的cron配置文件，用crontab -e 命令来定义；<br /><br />举一例：让机器在每天8点30分重新启动；<br /><br />关于时间格式中有7个字段。我们可以直接更改或者添加，当然这是系统任务调用。举个例子，比如我在每天的早上8点30分重新启动机器，就可以在<br />/etc/crontab中加入下面的两句，第一句就是注释了。以#号开始，后面写一个自己能知道这是什么任务的备注；<br /><br /><br /># reboot OS<br />30 8 * * * root /sbin/reboot<br /><br />第一段应该定义的是：分钟，表示每个小时的第几分钟来执行。范围是从0-59<br />第二段应该定义的是：小时，表示从第几个小时来执行，范围是从0-23<br />第三段应该定义的是：日期，表示从每个月的第几天执行，范围从1-31<br />第四段应该定义的是：月，表示每年的第几个月来执行，范围从1-12<br />第五段应该定义的是：周，表示每周的第几天执行，范围从0-6，其中 0表示星期日。<br />每六段应该定义的是：用户名，也就是执行程序要通过哪个用户来执行，这个一般可以省略；<br />第七段应该定义的是：执行的命令和参数。<br /><br />对比上面的例子就知道，30是不是分钟？？8是不是小时？如果有*代表的地方，表示全部，也就是说，每个月，每天，每星期都要执行。root 表示用root用户执行，命令是/sbin/reboot ，也就是说，系统在每天 8点30分重新启动；<br /><br />我们可以把每天8点30分重新启动的计划任务写入cron全局性配置文件中，也可以定义在root用户自己的cron配置文件中。如果定义在root自己的配置文件，请用root身份来执行 crontab -e 来修改配置文件；crontab -e 进入修改配置文件的过程，其实和vi的用法一样，请参看vi 的用法：《文件编辑器 vi》<br /><br />让配置文件生效：如果让配置文件生效，还得重新启动cron，切记，既然每个用户下的cron配置文件修改后。也要重新启动cron服务器。<br /><br />在Fedora 和Redhat中，我们应该用；<br /><br /><br />[root@localhost ~]# /etc/init.d/crond restart<br /><br />如果让crond 在开机时运行，应该改变其运行级别；<br /><br /><br />[root@localhost ~]# chkconfig --levels 35 crond on<br /><br />在Slackware中，如果开机自动运行；<br /><br />查看/etc/rc.d/rc.M文件是否有如的行，如果没有就加上，大多是有的；<br /><br /><br /># Start crond (Dillon's crond):<br />if [ -x /usr/sbin/crond ]; then<br />  /usr/sbin/crond -l10 >>/var/log/cron 2>&1<br />&lt;/cdoe><br />&lt;b><br />如果想让立即让cron重启生效，也可以用下面的办法；<br />&lt;/b><br />&lt;code><br />[root@localhost ~]# pgrep crond 注：查看crond服务器是否运行；<br />2022<br />[root@localhost ~]# pkill crond 注：杀死crond；<br />[root@localhost ~]# pgrep crond 注：查看crond是否退出；<br />[root@localhost ~]# /usr/sbin/crond 注：启动crond；<br />[root@localhost ~]# pgrep crond 注：查看crond 是否已经运行得起来了；<br />3883<br /><br /><br />2.2.3 关于同一时间，同时执行多个任务的定义方法；<br /><br /><br />我们在前面已经说过，在全局性配置文件中，有类似如下的段落；<br /><br /><br />1 * * * * root run-parts /etc/cron.hourly 注：表示每个小时的第一分钟，开始执行/etc/hourly目录下的可执行程序或脚本；<br />2 4 * * * root run-parts /etc/cron.daily 注：表示每天的4点2分，开始执行/etc/cron.daily目录下的可执行程序或脚本；<br />22 4 * * 7 root run-parts /etc/cron.weekly 注：每年第7个周4点我22分，开始执行 /etc/cron.weekly目录下的可执行程序或脚本；<br />42 4 1 * * root run-parts /etc/cron.monthly 注：每月第1天的4点42分，开始执行/etc/cron.monthly目录下的可执行程序或脚本；<br /><br />举例来说，我想在每天5点10分来重新启动httpd 服务器，与此同时，我们也可以同时下载一个ISO文件。如果我们按书写计划任务的规则一条一条的来书写，并添加到全局是有点麻烦。不如写一个脚本放在/etc/crond.daily目录中。然后把其权限设置为755 （关于权限的设置，请参考：《Linux 文件和目录的属性》）。<br /><br />当然我们得改一改上面的 带有/etc/cron.daily那行，改为如下；<br /><br /><br />10 5 * * * root run-parts /etc/cron.daily<br />&lt;/cdoe><br />然后我们到/etc/crond.daily目录中创建两个文件，一个是用来重启httpd服务器的，如下；<br />&lt;code><br />[root@localhost cron.daily]# touch httpd.sh<br />[root@localhost cron.daily]# chmod 755 httpd.sh<br />[root@localhost cron.daily]# echo "/etc/init.d/httpd restart" > httpd.sh<br />[root@localhost cron.daily]# more httpd.sh<br />/etc/init.d/httpd restart<br /><br />如果我想在每天5点20分下载FC5的镜像，可以再创建一个文件fc5down.sh<br /><br /><br />[root@localhost cron.daily]# touch fc5down.sh<br />[root@localhost cron.daily]# chmod 755 fc5down.sh<br />[root@localhost cron.daily]# echo "/usr/bin/wget http://mirrors.kernel.org/fedora/core/5/i386/iso/FC-5-i386-DVD.iso" > fc5down.sh<br />[root@localhost cron.daily]# more fc5down.sh<br />/usr/bin/wget http://mirrors.kernel.org/fedora/core/5/i386/iso/FC-5-i386-DVD.iso<br /><br />然后我们重新启动一下crond就行了；<br /><br /><br />[root@localhost cron.daily]# pkill crond<br />[root@localhost cron.daily]# prep crond<br />[root@localhost cron.daily]# crond&<br /><br />注意：我只是想说明一下，在同一时间 执行多个计划任务的简单用法，并不是有意教给您每天早上都下载FC5的映像。我举这个例子是为了初学者了解这个功能。如果您有好多的任务在某一时刻执行，那就自己写脚本文件。放在/etc目录下的cron.hourly 、cron.daily 、cron.weekly 、cron.monthly 目录中。凡是放进这些目录的可执行脚本，都能在约定的时间内准确执行。每个目录有每个目录的用途；<br /><br /><br />2.2.4 对于用户自身的cron 配置文件的说明；<br /><br /><br />每个用户都有自己的cron配置文件，通过crontab -e 就可以编辑，一般的情况下，在Fedora和Redhat的发行版，我们编辑好用户的cron配置文件保存退出后，系统会自动就存放于/var/spool/cron/目录中，文件以用户名命名。在Slackware中是位于/var/spool/cron/crontabs/目录中。其它的发行版都差不多，有点类似。自己找找吧；查看用户的计划任务是crontab -l <br /><br /><br />crontab -e 注：编辑用户的cron配置文件；<br />crontab -l 注：查看用户的计划任务；<br /><br />比如我用beinan用户来运行crontab -e ；<br /><br /><br />[beinan@localhost ~]＄ id 注：判断所用用户身份；<br />uid=500(beinan) gid=500(beinan) groups=500(beinan)<br />[beinan@localhost ~]＄ crontab -e 注：编辑用户beinan的计划任务；<br /><br />我们在里面定义一个任务；<br /><br /><br />40 20 * * * /usr/bin/wget http://mirrors.kernel.org/fedora/core/5/i386/iso/FC-5-i386-DVD.iso<br /><br />保存退出后，我们用下面的命令来查看beinan用户的计划任务；<br /><br /><br />[beinan@localhost ~]＄ crontab -l<br />40 20 * * * /usr/bin/wget http://mirrors.kernel.org/fedora/core/5/i386/iso/FC-5-i386-DVD.iso<br /><br />配置好后，我们还要重新启动crond服务器，每个用户cron配置文件的改动都得重新启动crond服务器；前面已经说过了，这里省略；值得注意的是重启crond服务器，需要root权限，您可以用su命令切换到root 用户，然后再来重启crond；<br /><br /><br />在Fedora或Redhat等以RPM包管理的发行版中；<br /><br /> <br /><br />[beinan@localhost ~]＄ su<br />口令：<br />[root@localhost beinan]# /etc/init.d/crond restart<br />停止 crond： [确定]<br />启动 crond： [确定]<br /><br /><br />也可以先杀死crond，再运行crond命令的办法来启动；<br /><br /> <br /><br />[root@localhost beinan]# pkill crond<br />[root@localhost beinan]# pgrep crond<br />[root@localhost beinan]# /usr/sbin/crond<br />[root@localhost beinan]# pgrep crond<br />6664<br /><br /><br />3、计划任务的应用范围；<br /><br /><br />计划任务主要是让系统自动完成一些工作。比如我们可以让系统自动在某一时刻清理或备份httpd服务器的日志，然后重新启动httpd服务器，这对网络管理员来说是很重要的。也可以让系统自动清空位于/tmp目录的垃圾文件。<br /><br />另外值得一提的是，LinuxSir.Org 有很多子站，每个子站都有RSS，能让这些站点的RSS相互投递，也是用cron来完成，比如是在早上4点左右开始执行这个任务。这是一个极为耗费资源的过程，如果不是放在在线人少的时候，基本无法完成，所以只能放在早上进行。作为SIR的管理员，不可能每天早上4点起来点鼠标来完成这些事吧。所以最好的办法就是通过cron来自动运行，以在服务器最清闲的时候来完成这项工作；
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/153724#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, 07 Jan 2008 17:51:14 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/153724</link>
        <guid>http://piaochunzhi.javaeye.com/blog/153724</guid>
      </item>
      <item>
        <title>Spring 2.0 的 IOC 问题！？？</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/80661" style="color:red;">http://piaochunzhi.javaeye.com/blog/80661</a>&nbsp;
          发表时间: 2007年05月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
	&lt;bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		&lt;property name="dataSource" ref="dataSource" />
		&lt;property name="mappingResources">
			&lt;list>
				&lt;value>pojo/Euser.hbm.xml&lt;/value>
			&lt;/list>
		&lt;/property>
		&lt;property name="hibernateProperties">
			&lt;props>
				&lt;prop key="hibernate.dialect">
					org.hibernate.dialect.Oracle9Dialect
				&lt;/prop>
				&lt;prop key="hibernate.show_sql">true&lt;/prop>
			&lt;/props>
		&lt;/property>
	&lt;/bean>

	&lt;bean id="baseDao" class="common.dao.BaseDaoImp">
		&lt;property name="sessionFactory" ref="sessionFactory" />
	&lt;/bean>
	
	&lt;bean id="queryDao" class="common.dao.QueryDaoImp">
		&lt;property name="sessionFactory" ref="sessionFactory" />
	&lt;/bean>
	
	&lt;bean id="userDAO" class="common.dao.UserDAO">
		&lt;property name="sessionFactory" ref="sessionFactory" />
	&lt;/bean>
	
	
	&lt;bean id="pageQueryDao" class="common.dao.PageQueryDaoImp">
		&lt;property name="sessionFactory" ref="sessionFactory" />
	&lt;/bean>

	&lt;bean name="baseService" class="common.BaseService">
		&lt;property name="baseDao" ref="baseDao" />
		&lt;property name="pageQueryDao" ref="pageQueryDao" />
		&lt;property name="queryDao" ref="queryDao" />
	&lt;/bean>
</pre><br /><br /><br /><pre name="code" class="java">
public class BaseService {
    protected BaseDao baseDao;
    protected PageQueryDao pageQueryDao;
    protected QueryDao queryDao;
    
    protected Log log = LogFactory.getLog(getClass());
    /**
     * @param dao
     *            The dao to set.
     */
    public void setBaseDao(BaseDao dao) {
        this.baseDao = dao;
    } 

    public void setPageQueryDao(PageQueryDao pageQueryDao) {
		this.pageQueryDao = pageQueryDao;
	}

	public void setQueryDao(QueryDao queryDao) {
		this.queryDao = queryDao;
	}

}
</pre><br /><br /><br />以上是我的代码 ！！！！！<br /><br /><pre name="code" class="java">
ApplicationContext context = new ClassPathXmlApplicationContext("xms-web.xml");
	BaseService bs = (BaseService) context.getBean("baseService");
if(baseDao==null){
   System.out.print("==========================");
}
</pre><br /><br />总是 打印 ==========================<br /><br /><br />谁能指点指点
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/80661#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, 17 May 2007 18:10:12 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/80661</link>
        <guid>http://piaochunzhi.javaeye.com/blog/80661</guid>
      </item>
      <item>
        <title>Spring-------的低耦合高内聚（到底是在Spring框架下 ，还是脱离Spring框架）</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/67823" style="color:red;">http://piaochunzhi.javaeye.com/blog/67823</a>&nbsp;
          发表时间: 2007年04月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Spring-------的低耦合高内聚 指的是<br /><br />在Spring框架下 类于类之间，还是脱离Spring框架之下而言
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/67823#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>Wed, 04 Apr 2007 11:01:34 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/67823</link>
        <guid>http://piaochunzhi.javaeye.com/blog/67823</guid>
      </item>
      <item>
        <title>显示byte【】图片的问题，出现一个图片“叉 ”很难看 我想什么也不显示</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/65483" style="color:red;">http://piaochunzhi.javaeye.com/blog/65483</a>&nbsp;
          发表时间: 2007年03月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
byte b[];
b=groupbean.getAd();
if(b!=null){
	response.setContentType("image/gif");
	javax.servlet.ServletOutputStream sout1=response.getOutputStream();
	try{
		sout1.write(b);
	}
	catch(Exception ex){
		ex.printStackTrace();
	}
	finally{
		sout1.close();
	}
}else{
	System.out.print("adpi---------------null");
}
</pre><br />IF b!=null 的时候 可以显示图片！<br /><br />b==null  的时候 出现一个 图片 “叉 ” 很难看 ，我想什么也不显示，不知道 如何处理 ，希望 有人指点！
          <br/>
          <span style="color:red;">
            <a href="http://piaochunzhi.javaeye.com/blog/65483#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, 26 Mar 2007 09:20:07 +0800</pubDate>
        <link>http://piaochunzhi.javaeye.com/blog/65483</link>
        <guid>http://piaochunzhi.javaeye.com/blog/65483</guid>
      </item>
      <item>
        <title>转过来 ，非常好 的 关于 J2EE</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://piaochunzhi.javaeye.com/blog/59494" style="color:red;">http://piaochunzhi.javaeye.com/blog/59494</a>&nbsp;
          发表时间: 2007年03月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>1.我们谈论了J2EE，但究竟什么是J2EE？它是规范吗？它是技术吗？它是在什么样的背景下出现的，为了解决什么？<br />
2.我们也谈架构？但究竟什么是架构？架构出于什么目的？架构的目标是什么呢？<br />
3.我们频繁的使用Struts,但它帮我们解决什么呢？可能有人会说它是MVC的实现，但这不是问题的答案.MVC它又解决了什么呢？</p>
<p>&nbsp;</p>
<p><span class="tpc_content">1. J2EE是规范，是一种JSR标准，有详细文档，阐述J2EE提供哪些功能，可以下载这样文档，当然还有一些代码接口，这是典型Java世界中的框架代码+标准文档形式，这是只有自由世界才有的规范，在微软MS世界你是绝对不会看到的，所以，从微软转过来的，会晕，会不适应，不能再按照他们以前的经验来看待自由的新世界。<br />
<br />
2.架构是就软件平台的搭建和设计规划，目的是实现软件最大的可维护性和可拓展性，延续软件的生命，就象人生下来，整个架构都有了，虽然一些器官不能用到（例如生殖器官），但是一生下来还是有这些器官，这就是架构设计的优势，没有架构设计的软件是看不到明天，生下的小孩就不会有生殖器官，因为他认为小孩不需要，但是他没有看到小孩20岁以后的未来。<br />
<br />
架构就是要有预见性，特别是Java世界，技术流派众多，优劣共存，让人吃药的技术比比皆是，不象微软世界，有微软这个专制强权的架构设计者和提供者告诉你用什么，除此之外别无选择，在Java自由世界，你可能不小心走上一个不归路，软件架构一旦错误，就象出发的方向发生问题，南辕北辙成语就是说这个意思，花再多精力再多钱，再强的人都没有用，项目照样失败。<br />
<br />
所以，在Java世界选择技术，就象女孩子到自由市场淘货，必须冒被骗失败的风险，但是其中乐趣也是不言而喻的，你会成为技术专家，当然，如果你想很多找到合适的架构设计，那么借助外力，象J道都提供这样架构设计服务，可以在短时间介绍一些这个自由市场哪些东西是性价比好，值得买，找个有信誉的内行当地人做咨询，就是这个道理。<br />
<br />
目前Java世界，架构设计主要是框架选择，如果你的团队非常弱，可能只会基础的Java编程，那么选择强制性框架就比较好，这样可以在保证软件质量情况下，不让不太懂的人胡作非为，破坏软件整体的可维护性，好的框架甚至只需要XML配置就可以，这样，OO能力差一些人，就不需编程代码，配置配置XML就可以，这样，通过架构设计，可以充分发挥现有人员的长处，克服他们的短处。<br />
<br />
所以，为什么过去数据库专家DBA年薪20万，而现在架构师年薪20万。而且DBA年薪20万已经成为过去时，因为人们已经发现，再好的数据库设计，只是数据库设计，不是程序语言设计，更多维护烦琐和复杂工作我们是需要修改的程序代码，所以，大家才开始重视应用程序代码，并且发现程序代码控制比数据库设计更难控制，所以有了OO体系专门对付程序代码，进而有了框架，从而诞生比DBA更重要的architect了。<br />
<br />
3.关于struts重要性，还是必须从程序代码可维护性来讲，也就是从OO角度讲，Struts能够通过MVC模式将表现层进行细分，实现表现层内部各个细分部分的最大解耦，然后，Struts也可以将页面离散无规律的数据转变为对象，供业务层服务，也就是Struts表现层实际是业务层的服务者，为其提供对象化的枪支弹药，而业务层则可以围绕这些对象实现对象化编程，从而实现更好的可维护性，Evans DDD对业务层进行细分，这些都是基于对象基础，当然持久层不用说，和表现层一样也是业务层的服务者，为其提供对象化的枪支弹药，不过这些对象是从数据库里拿来的，是从一个非对象化，离散的、关系型的数据库拿来的，Hibernate等框架必须将他们转为对象，给业务层使用。<br />
<br />
所有这些框架，都是保证我们业务逻辑完全OO，这个前提是：你相信只有OO才是目前实现软件最大维护性和拓展性的适当方式，虽然可能不是最好的，但他是目前最合适的，否则全世界软件工业不会花这么多力气在OO上了。<br />
<br />
因为我们国内将软件看成数学，软件论文实际是数学公式论文，可以发生了软件研究方向的偏离，没有走上OO正确研究方向，这样导致很多程序员学校毕业后，根本没有OO基本意识，甚至有人抵触OO，我从出版社内部销售资料看到：Foxpro等数据库书籍名列销售前列，我是欲哭无泪，中国人的软件误区中还要走多少年。<br />
<br />
所有这些，必须从我们教育体系寻找，这里面话题太多，我想其中一个问题还是：中微软毒太深，因为微软已经帮你做了架构的事情，你唯一要做的就是拿来某个软件，按照其说明书做，但