java基础知识,你都知道么?

Java 基础 axman 考验你的 Java 基础
1. 简述逻辑操作 (&,|,^) 与条件操作 (&&,||) 的区别。 (15 )
2. 下面程序运行会发生什么结果 ? 如果有错误,如何改正 ? (15 )
interface A{
 int x = 0;
}
class B{
 int x =1;
}
class C
    extends B implements A {
 public void pX(){
    System.out.println(x);
 }
 public static void main(String[] args) {
    new C().pX();
 }
}
}
3. 简述 Java Server Page Servlet 的联系和区别。 (20 )
4.XML 文档定义有几种形式?它们之间有何本质区别?
解析 XML 文档有哪几种方式? (20 )
5. 简述 synchronized java.util.concurrent.locks.Lock 的异同? (15 )
6.EJB 规范规定 EJB 中禁止的操作有哪些? (15 )
 
7. 最后还有一题考考你的眼力 :
 
public String toString(){
return this + "@" + this.hashCode();
}
这个 toString() 方法实现有无不当的地方 ?(toString 方法其实可以按你想输出的任何内容输出一些该类的信息 )
 
 
答案:
1. 简述逻辑操作 (&,|,^) 与条件操作 (&&,||) 的区别。 (15 )
区别主要答两点 :
a. 条件操作只能操作布尔型的,而逻辑操作不仅可以操作布尔型 , 而且可以操作数值型
b. 逻辑操作不会产生短路 . :
int a = 0;
int b = 0;
 
if( (a = 3) > 0 || (b = 3) > 0 ) // 操后 a =3,b=0.
if( (a = 3) > 0 | (b = 3) > 0 ) // 操后 a =3,b=3.
答对第一点得 5 分,答对第二点得 10 .
 
本题考察最最基本的知识 , 但仍然有很多大牛级开发人员下马,任何语言在开始的部分
都会详细介绍这些基本知识,但除了学习第一种语言时,没有人在学习新的语言时愿意
花五分钟来复习一下 .
 
 
2. 下面程序运行会发生什么结果 ? 如果有错误,如何改正 ? (15 )
interface A{
 int x = 0;
}
class B{
 int x =1;
}
class C
    extends B implements A {
 public void pX(){
    System.out.println(x);
 }
 public static void main(String[] args) {
    new C().pX();
 }
}
}
 
本题在编译时会发生错误 ( 错误描述不同的 JVM 有不同的信息,意思就是未明确的 x 调用,
两个 x 都匹配,就象在同时 import java.util java.sql 两个包时直接声明 Date 一样 )
 
本题主要考察对接口和类的最最基本的结构的了解 . 对于父类的变量,可以用 super.x
明确,而接口的属性默认隐含为 public static final. 所以可以通过 A.x 来明确 .
 
 
3. 简述 Java Server Page Servlet 的联系和区别。 (20 )
本题不用多说,在答相同点时应该明确知道 jsp 编译后是 " servlet" " 不是 Servlet"
答区别时应该回答出 " 侧重于 ( 视图 / 控制逻辑 )". 其它可根据情况加减分值 . 知识很简单,
但从面试的角度看,被试者不仅要能知道它们的区别,而且要能比较准确地表达出来 (
后写文档要能让别人看得懂,不产生歧义 ) ,回答 "jsp 编译后就是 servlet" 视为错误,回答
"jsp 用于视图, servlet 用于控制逻辑 " 视为错误,应该用侧重于,主要 ( 多数 ) 用于等词语
表达 .
 
 
4.XML 文档定义有几种形式?它们之间有何本质区别?
解析 XML 文档有哪几种方式? (20 )
本题三个答题点 :
a: 两种形式 dtd schema
b: 本质区别 :schema 本身是 xml 的,可以被 XML 解析器解析 ( 这也是从 DTD 上发展 schema
根本目的 )
c: 两种主要方式 :dom sax. 答出两种得全分,如能答出 saxt ,或其它 ( 在答出 dom sax 的基
础上,如果应试者认为其它方式也可以视为对 xml 的解析应该允许 . 但没有答出 dom sax
其它方式说成是对 XML 的解析不得分 ) 应该加分 .
 
5. 简述 synchronized java.util.concurrent.locks.Lock 的异同? (15 )
 
主要相同点 :
Lock 能完成 synchronized 所实现的所有功能 .( 其它不重要 )
主要不同点 :
Lock 有比 synchronized 更精确的线程语义和更好的性能 ( 在相同点中回答此点也行 )
synchronized 会自动释放锁 . Lock 一定要求程序员手工释放 . 并且必须在 finally 从句
中释放,如果没有答出在 finally 中释放不得分 . 就如 Connection 没有在 finally 中关闭一
. 连最基本的资源释放都做不好,还谈什么多线程编程 .
 
6.EJB 规范规定 EJB 中禁止的操作有哪些? (15 )
共有 8 点,答出下列 3-4 点得满分 .
 
·             不能操作线程和线程 API( 线程 API 指非线程对象的方法如 notify wait )
·             不能操作 awt
·             不能实现服务器功能
·             不能对静态属生存取 .
·             不能使用 IO 操作直接存取文件系统
·             不能加载本地库 .
·             不能将 this 作为变量和返回 .
·             不能循环调用 .
 
7
public String toString(){
return this + "@" + this.hashCode();
}
 
 
会变成
 
public String toString(){
return String.valueOf(this) + "@" + String.valueOf(this.hashCode());
}
 
valueOf 方法又将去调用 toString();
/**
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
*/
这样好像会有问题
 
原文地址:
 
Java 本身没有这个能力,不过利用操作系统的命令可以做到。
 
public static String getMACAddress() {
String address = "";
String os = System.getProperty("os.name");
if ( os != null && os.startsWith("Windows")) {
try {
  String command = "cmd.exe /c ipconfig /all";
  Process p = Runtime.getRuntime().exec(command);
  BufferedReader br =
  new BufferedReader(
  new InputStreamReader(p.getInputStream()));
  String line;
  while ((line = br.readLine()) != null) {
    if (line.indexOf("Physical Address") > 0) {
      int index = line.indexOf(":");
      index += 2;
      address = line.substring(index);
    break;
}
}
  br.close();
  return address.trim();
}
catch (IOException e) { }
}
return address;
}
原文地址:
 
 
axman equal 的深入研究
equals 方法的重要性毋须多言,只要你想比较的两个对象不愿是同一对象,你就应该实现
equals 方法,让对象用你认为相等的条件来进行比较 .
 
下面的内容只是 API 的规范,没有什么太高深的意义,但我之所以最先把它列在这儿,是因为
这些规范在事实中并不是真正能保证得到实现 .
 
1. 对于任何引用类型, o.equals(o) == true 成立 .
2. 如果 o.equals(o1) == true 成立,那么 o1.equals(o)==true 也一定要成立 .
3. 如果 o.equals(o1) == true 成立且 o.equals(o2) == true 成立,那么
o1.equals(o2) == true 也成立 .
4. 如果第一次调用 o.equals(o1) == true 成立再 o o1 没有改变的情况下以后的任何次调用
都成立 .
5.o.equals(null) == true 任何时间都不成立 .
 
以上几条规则并不是最完整的表述,详细的请参见 API 文档 .
 
对于 Object 类,它提供了一个最最严密的实现,那就是只有是同一对象是, equals 方法才返回 true ,也就是人们常说的引用比较而不是值比较 . 这个实现严密得已经没有什么实际的意义,所以在具体子类 ( 相对于 Object 来说 ) 中,如果我们要进行对象的值比较,就必须实现自己的 equals 方法 .
 
先来看一下以下这段程序 :
    public boolean equals(Object obj)
    {
        if (obj == null) return false;
        if (!(obj instanceof FieldPosition))
            return false;
        FieldPosition other = (FieldPosition) obj;
        if (attribute == null) {
            if (other.attribute != null) {
                return false;
            }
        }
        else if (!attribute.equals(other.attribute)) {
            return false;
        }
        return (beginIndex == other.beginIndex
            && endIndex == other.endIndex
            && field == other.field);
    }
 
 
这是 JDK java.text.FieldPosition 的标准实现,似乎没有什么可说的 .
 
我信相大多数或绝大多数程序员认为,这是正确的合法的 equals 实现 . 毕竟它是 JDK API 实现啊 .
 
还是让我们以事实来说话吧 :
package debug;
 
import java.text.*;
 
public class Test {
 public static void main(String[] args) {
    FieldPosition fp = new FieldPosition(10);
    FieldPosition fp1 = new MyTest(10);
    System.out.println(fp.equals(fp1));
    System.out.println(fp1.equals(fp));
 }
}
class MyTest extends FieldPosition{
 int x = 10;
 public MyTest(int x){
    super(x);
    this.x = x;
 }
 public boolean equals(Object o){
    if(o==null) return false;
    if(!(o instanceof MyTest )) return false;
    return ((MyTest)o).x == this.x;
 }
}
 
运行一下看看会打印出什么 :
 
System.out.println(fp.equals(fp1)); 打印 true
System.out.println(fp1.equals(fp)); 打印 flase
 
两个对象,出现了不对称的 equals 算法 . 问题出在哪里 ( 脑筋急转弯:当然出在 JDK 实现的 BUG)?
 
我相信有太多的程序员 ( 除了那些根本不知道实现 equals 方法的程序员外 ) 在实现 equals 方法
时都用过 instanceof 运行符来进行短路优化的,实事求是地说很长一段时间我也这么用过。
太多的教程,文档都给了我们这样的误导。而有些稍有了解的程序员可能知道这样的优化可能
有些不对但找不出问题的关键。另外一种极端是知道这个技术缺陷的骨灰级专家就提议不要这
样应用。
 
我们知道, " 通常 " 要对两个对象进行比较,那么它们 " 应该 " 是同一类型。所以首先利用 instanceof
运行符进行短路优化,如果被比较的对象不和当前对象是同一类型则不用比较返回 false ,但事实
上, " 子类是父类的一个实例 " ,所以如果子类 o instanceof 父类,始终返回 true ,这时肯定
不会发生短路优化,下面的比较有可能出现多种情况,一种是不能造型父类而抛出异常,另一种
是父类的 private 成员没有被子类继承而不能进行比较,还有就是形成上面这种不对称比较。可能
会出现太多的情况。
 
 
那么,是不是就不能用 instanceof 运行符来进行优化?答案是否定的, JDK 中仍然有很多实现是正
确的,如果一个 class final 的,明知它不可能有子类,为什么不用 instanceof 来优化呢?
 
为了维护 SUN 的开发小组的声誉,我不说明哪个类中,但有一个小组成员在用这个方法优化时在后加
加上了加上了这样的注释:
 
        if (this == obj)                      // quick check
            return true;
        if (!(obj instanceof XXXXClass))         // (1) same object?
            return false;
 
可能是有些疑问,但不知道如何做(不知道为什么没有打电话给我 ......
 
那么对于非 final 类,如何进行类型的 quick check 呢?
 
if(obj.getClass() != XXXClass.class) return false;
 
用被比较对象的 class 对象和当前对象的 class 比较,看起来是没有问题,但是,如果这个类的子类
没有重新实现 equals 方法,那么子类在比较的时候, obj.getClass() 肯定不等于 XXXCalss.class
也就是子类的 equals 将无效,所以 if(obj.getClass() != this.getClass()) return false; 才是正
确的比较。
 
 
是否 equals 方法一定比较的两个对象就一定是要同一类型?上面我用了 " 通常 " ,这也是绝大多数程序
员的愿望,但是有些特殊的情况,我们可以进行不同类型的比较,这并不违反规范。但这种特殊情况
是非常罕见的,一个不恰当的例子是, Integer 类的 equals 可以和 Sort 做比较,比较它们的 value 是不
是同一数学值。(事实上 JDK API 中并没有这样做,所以我才说是不恰当的例子)
 
在完成 quick check 以后,我们就要真正实现你认为的 相等 。对于如果实现对象相等,没有太高
的要求,比如你自己实现的 类,你可以认为只要 name 相同即认为它们是相等的,其它的 sex
ago 都可以不考虑。这是不完全实现,但是如果是完全实现,即要求所有的属性都是相同的,那么如
何实现 equals 方法?
 
 class Human{
private String name;
private int ago;
private String sex;
        ....................
        public boolean equals(Object obj){
quick check.......
Human other = (Human)ojb;
return this.name.equals(other.name)
&& this.ago == ohter.ago
&& this.sex.equals(other.sex);
}
}
 
这是一个完全实现,但是,有时 equals 实现是在父类中实现,而要求被子类继承后 equals 能正确的工
作,这时你并不事实知道子类到底扩展了哪些属性,所以用上面的方法无法使 equals 得到完全实现。
一个好的方法是利用反射来对 equals 进行完全实现:
 
        public boolean equals(Object obj){
quick check.......
Class c = this.getClass();
Filed[] fds = c.getDeclaredFields();
for(Filed f:fds){
if(!f.get(this).equals(f.get(obj)))
return false;
}
return true;
}
 
 
为了说明的方便,上明的实现省略了异常,这样的实现放在父类中,可以保证你的子类的 equals 可以按
你的愿望正确地工作。
 
关于 equals 方法的最后一点是:如果你要是自己重写(正确说应该是履盖)了 equals 方法,那同时就一
定要重写 hashCode(). 为是规范,否则 .............
我们还是看一下这个例子:
 
public final class PhoneNumber {
    private final int areaCode;
    private final int exchange;
    private final int extension;
 
    public PhoneNumber(int areaCode, int exchange, int extension) {
        rangeCheck(areaCode, 999, "area code");
        rangeCheck(exchange, 99999999, "exchange");
        rangeCheck(extension, 9999, "extension");
        this.areaCode = areaCode;
        this.exchange = exchange;
        this.extension = extension;
    }
 
    private static void rangeCheck(int arg, int max, String name) {
        if(arg < 0 || arg > max)
            throw new IllegalArgumentException(name + ": " + arg);
    }
 
    public boolean equals(Object o) {
        if(o == this)
            return true;
        if(!(o instanceof PhoneNumber))
            return false;
        PhoneNumber pn = (PhoneNumber)o;
        return pn.extension == extension && pn.exchange == exchange && pn.areaCode == areaCode;
    }
}
 
 
注意这个类是 final 的,所以这个 equals 实现没有什么问题。
 
我们来测试一下 :
    public static void main(String[] args) {
        Map hm = new HashMap();
        PhoneNumber pn = new PhoneNumber(123, 38942, 230);
        hm.put(pn, "I love you");
        PhoneNumber pn1 = new PhoneNumber(123, 38942, 230);
        System.out.println(pn);
        System.out.println("pn.equals(pn1) is " + pn.equals(pn1));
        System.out.println(hm.get(pn1));
        System.out.println(hm.get(pn));
    }
 
既然 pn.equals(pn1) ,那么我 put(pn,"I love you"); 后, get(pn1) 这什么是 null 呢?
答案是因为它们的 hashCode 不一样,而 hashMap 就是以 hashCode 为主键的。
 
所以规范要求,如果两个对象进行 equals 比较时如果返回 true ,那么它们的 hashcode 要求返回相等的值。
 
原文地址:
 
为什么要始终使用 PreparedStatement代替Statement?
JDBC 应用中,如果你已经是稍有水平开发者,你就应该始终以 PreparedStatement 代替 Statement. 也就是说,在任何时候都不要使用 Statement.
基于以下的原因 :
. 代码的可读性和可维护性 .
虽然用 PreparedStatement 来代替 Statement 会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说 . 都比直接用 Statement 的代码高很多档次 :
 
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
 
perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();
 
不用我多说,对于第一种方法 . 别说其他人去读你的代码,就是你自己过一段时间再去读,都会觉得伤心 .
 
.PreparedStatement 尽最大可能提高性能 .
每一种数据库都会尽最大努力对预编译语句提供最大的性能优化 . 因为预编译语句有可能被重复调用 . 所以语句在被 DB 的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中 ( 相当于一个涵数 ) 就会得到执行 . 这并不是说只有一个 Connection 中多次执行的预编译语句被缓存,而是对于整个 DB 中,只要预编译的语句语法和缓存中匹配 . 那么在任何时候就可以不需要再次编译而可以直接执行 . statement 的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配 . 比如 :
insert into tb_name (col1,col2) values ('11','22');
insert into tb_name (col1,col2) values ('11','23');
即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义 . 事实是没有数据库会对普通语句编译后的执行代码缓存 . 这样每执行一次都要对传入的语句编译一次 .
 
当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果 . 以保存有更多的空间存储新的预编译语句 .
 
. 最重要的一点是极大地提高了安全性 .
 
即使到目前为止,仍有一些人连基本的恶义 SQL 语法都不知道 .
String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";
如果我们把 [' or '1' = '1] 作为 varpasswd 传入进来 . 用户名随意,看看会成为什么 ?
 
select * from tb_name = ' 随意 ' and passwd = '' or '1' = '1';
因为 '1'='1' 肯定成立,所以可以任何通过验证 . 更有甚者,把 [';drop table tb_name;] 作为 varpasswd 传入进来,则 select * from tb_name = ' 随意 ' and passwd = '';drop table tb_name; 有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行 .
 
而如果你使用预编译语句 . 你传入的任何内容就不会和原来的语句发生任何匹配的关系 .( 前提是数据库本身支持预编译,但上前可能没有什么服务端数据库不支持编译了,只有少数的桌面数据库,就是直接文件访问的那些 ) 只要全使用预编译语句,你就用不着对传入的数据做任何过虑 . 而如果使用普通的 statement ,有可能要对 drop ,等做费尽心机的判断和过虑 .
 
上面的几个原因,还不足让你在任何时候都使用 PreparedStatement ?
原文地址:
 
 
一个利己线程调度实例?
所谓利己线程,就是在运行时不考虑其它线程的运行权限和时间分配,一心只顾自己运行完成了事的这种线程,比如 :while(true){............}
但是 , 如果 {..........} 的代码中要调用一些资源,就一定要 sleep ,让资源有空闲的时间来让本线程获取,也许这些资源不是当前线程一方要求调用,但无论如何要空闲一定的时间,即使资源空闲下来时本线程只能调用很少一部份,不然真的就死锁了 .
 
在图形编程中,加载一个图形是异步的,然后组件会调用观察类 ImageObserver 来不断让图形加载和显示进行更新直到完成 . 因为图形组件的顶级对象 Component 已经实现 ImageObserver ,所以一般来说如果要加载一个 Image ,只要在 drawImage 方法中调用 this( 自己 ) 作为观察者就行 .
 
但是,如果我们要把一个源图象缩放后输出,或把多个源图象合并成一个图象输出 ( 图形计数器就是把很多种 0-9 的数字图片合并成一个图片 ) 输出,那就是在内存中先生生成一个 BufferedImage 对象,然后把源图象 draw BufferedImage 的一定位置,再把 BufferedImage 编码输出到一个输出流如文件或网页 . 因为 drawImage BufferedImage Graphics 对象调用的,一切都在内存中而根本没有可视组件,所以根本没有观察者对象,而 MediaTracker 对象同样要求一个组件对象构造,在这种时候也没法调用 .
 
 
BufferedImage bi = new BufferedImage( 目标宽,目标高, BufferedImage.TYPE_INT_RGB);
Graphics2D g =(Graphics2D)image.getGraphics();
Image src = Toolkit.getDefaultToolkit().getImage("d:/aaa.jpg");
不管你的 src 原来是多大,只要你 draw 时设定大小,就会以你设定的大小画到目标 bi 上,这就是
缩略图或合成图的方法 . 但在 g.drawImage(src ,坐标 x ,坐标 y ,宽,高,观察者 ); 调用时,因为没有一个观察者实例,一次调用 99% 不会成功 . 所以我是这样调用的 :
while (!(flag=g.drawImage(src, 0, 0, 240, 320, null))) ;
大家注意是如果 flag flase 就只有一个 ";" 也就是什么也不做直接进入下一次循环 .
我试过一般画一张新图要 10 多秒,如果是生成计数器,这在 servlet 中根本不行 . 没有人愿意用 10 秒的时间等一个计数器出来 . 后来我想让这个 servlet 实现观察者 . 就在
while (!(flag=g.drawImage(src, 0, 0, 240, 320, null))) {
 
}
中调试它每次 getWidth(null) log 并打印出来,结果发现如果改成
    while (!(flag=g.drawImage(src, 0, 0, 240, 320, null))) {
    System.out.println(src.getWidth(null));
}
却只要 200MS 0.2 秒左右就完成了 . 原来, System.out 时要调用 BIOS 的资源,这时线程要闲置等待,到反而让 src 资源有了 load 的时间 . 于是改成 :
    while (!(flag=g.drawImage(src, 0, 0, 240, 320, null))) {
    Thread.currentThread().sleep(1);
}
哈哈 , 成功了 .sleep 1,5,10MS 没有多大区别 , 都在 200MS 左右完成 , 一般不要再睡更多的时间 .
 
所以即使是利己线程的也要看它是否对其它资源的请求 , 真的应了那句话叫 " 予人方便 , 于己方便 !"
 
原文地址:
 
GBK GB2312 字符集的问题
有的用户比如叫扬璠,或是李珺。就不能正确显示她的名字,而显示一个扬? , ? ,其他中文没问题,就是这些比较偏怪的中文无法显示。这就是 GBK GB2312 的区别 , 你说的那几个字是 GBK 中的 ,GB2312 中根本没有 , 只好 ?? 了,使用 GBK 就行了。
 
原文地址:
 
怎样制作 ear,war文件?
方法一:
 
JDK CLASSPATH 下命令行打包:
用法: jar {ctxu}[vfm0M] [jar- 文件 ] [manifest- 文件 ] [-C 目录 ] 文件名 ...
选项:
-c 创建新的存档
-t 列出存档内容的列表
-x 展开存档中的命名的(或所有的〕文件
-u 更新已存在的存档
-v 生成详细输出到标准输出上
-f 指定存档文件名
-m 包含来自标明文件的标明信息
-0 仅限存储方式;使用非 ZIP 压缩格式
-M 不生成所有项的清单( manifest 〕文件
-i 为指定的 jar 文件产生索引信息
-C 改变到指定的目录,并且包含参数
如果指定的文件都是目录,将会使用递归方式加以处理。
必须以指定 'm' 'f' 选项的顺序,指定清单
manifest 〕文件名和存档文件名。
示例 1 :将两个 class 文件保存到名称为 'classes.jar' 的存档文件中:
jar cvf classes.jar Foo.class Bar.class
示例 2 :使用现有的清单( manifest )文件 'mymanifest' ,将 foo/ 目录
下的所有文件保存到名称为 'classes.jar' 的存档文件中:
jar cvfm classes.jar mymanifest -C foo/ .
 
 
war jar cvf webapp.war webapp/
ear: jar cvf enapp.ear enapp/
 
方法二:
weblogic classpath 下,
java weblogic.ant.taskdefs.ejb20.DDInit <target directory>
java weblogic.ant.taskdefs.war.DDInit <target directory>
java weblogic.ant.taskdefs.ear.DDInit <target directory>
jar cf jar-file files ...
 
方法三:
使用打包工具,比如 weblogic builder
原文地址:
 
乱码问题在 JAVA 平台的 jsp/servlet 中可以说是非常令初学者头痛的事 , 甚至很多 " 高手 ( 当然只是所谓的 , 如果连乱码都不能解决还叫什么高手 )" 都不知所措 .
 
我先说明 , 乱码问题绝对没有一种通用的方法来解决绝 , 除非你你都用 i18n 来定义和用 UTF 来传传输 , 显示 , 但这是不可能的 . 我们只有根本不同原因来用不同的解决方案 .
 
要从底层解决乱码 , 要求程序员要熟悉数据在网络上和内存中的每一个字节是来源和去向 , 这样才能从根本上解决 .
 
产生的原因 :
1: 数据传输入过程中没有按协议格式化 .
2: 没有根据当前环境决定显示方式 .
 
下面为了说明 , 我们只讨论汉字乱码产生的原因 :
从客户端提交给服务端 , 对于 POST 传送 , 目前的浏览器都能正确编码 , QueryString 方法是程序员控制的 , 很多程序员根本不对中文的 URL 格式化 , 直接用中文作为参数传送 , 对于 IE6 这样的智能程序高的浏览器可以自动格式化 , 而老版本的浏览器测原方传送 , 则服务器端程序不能正确地从标准输入中取得 . 应该先格式化编码。
 
如果网络上或内存中原如数据是正确的 , 但要用正确的方式从 byte 转换成系统能显示的字符集 . 假设 " " byte 表示为 78,63( 只是例子 ) ,但 78,63 有可能表示日文的ぬ , 那你就要告诉系统 , 你当前的 byte[] b 表示的是什么字符集 . 而我所见过的 jsp/servlet 容器中除了 resin
getParameter() 这个方法实现中都是 return new String(b//byte[]); 而没有指定字集 .WLS 我没的反编译 , 所以不知道它的 HTMLUtil 这个类在实现时是如何指定字符集还是没有。如果各种方法不能解决 , 我们只能对 BEA 不敬了 , ServletRequestWrapper decode 出来 , getParameter() 方法中直接 return new String(b,"GBK") 得了 . 这样省得在 XML 中配置又不起作用。同样从数据库中如果取得的数据乱码 , 我们只要把 JDBC ResultSet decode 出来 , 把其中的 getString(int column) 方法中的 return new String(b) 方法都强行加上 "GBK"
 
这样取数据保证正确了 , 然后再来解决显示的问题 , 即使你的数据在内存中是正确的 , 你也指定了正确的字符集参数 , 仍然不能保证你看到的是正确的 , 原因是系统知道这个编码是对的 , 但它没有这种字符集来显示 , 或你用来显示的字集不对 . 这就是 JSP <%@page contentType="text/html;charset=xxxx"%> 的作用 , 有人以为光这样就正确了 , 你要知道这句和 response.setContentType("text/html;charset=xxxx"); 是一样的 , 只它是告诉浏览器我现在发给你的内容是用 xxxx 字符集来解释的 , 只能在从网络上或内存中取得的数据是正确的前提下才有用 . 现在 servet 1.2 也支持设置客户端字符集的方法了 :setCharacterEncoding.
所以乱码问题绝不是一种方法能解决的 , 我们一定要知道它产生的原因 , 从底层来进行原始数据的转换才能解决 . 其实找原因也很简单 , HttpUtil 中加一个直接 getBytes() 方法 , 把得到的原始数据看看是不是你你传过来的 . 比如从 QueryString 传过来 " "aaa.jsp?name= , 那你看看它的 byte 中是不是我的值 , 如果是 , 说明传送没有问题 , 不是就是没有格式化 . 一步步下来 , 总是不难解决的。
 
原文地址:
 
 
 
 

Servlet&JSP 加载和启动servlet后,为一个servlet创建了一个还是多个实例?
如果你只是声明了一个普通 HttpServlet ,那肯定是一个实例多个线程在服务。而如果你声明的同时实现 SingleThreadModel 接口那么 Servlet 是单线程服务, Servlet 会在一个池里像 EJB 一样在为你服务。
 
原文地址:
 
WebLogic 里面的一个 class 修改了,需要重新启动 WebLogic 吗?
以下措施可以保证这一点,建议在开发过程中使用:
 
1. startWebLogic.cmd:
set STARTMODE=false
 
2. web.xml:
<servlet-mapping>
<servlet-name>loginA</servlet-name>
<url-pattern>/servlet/loginCheckA</url-pattern>
<load-on-startup>0</load-on-startup>
</servlet-mapping>
 
3. weblogic.xml:
<jsp-param>
<param-name>pageCheckSeconds</param-name>
<param-value>0</param-value>
</jsp-param>
4.Make sure that your servlet classes are not in your classpath which can cause this problem.
5. WLS console , 在该 web app Files 页中 , <Reload Period> 设为 1
 
原文地址:
 
Tomcat关于UTF-8JSP文件的BUG
刚才 , 我都要睡下了 , 朋友打来电话 , 他们公司新装了 TOMCAT5, 然后在编译 JSP , INCLUDE JSP 都出现了问题 . 就是编译后被 INCLUDE 的地方多了两个 "??" 而其它正常 , 而如果手工把被 INCLUDE 的内容 COPY 上去测没有问题 .
他们的工程师都不知道是什么问题 , 因为周一要发布出去 , 所以非常着急 .
 
我不知道大家听到这种情况会如何 , 我知道大多数人比我聪明 , 你肯定想到了 , 所以你没有必要再看了 . 我下面的内容只是对没有想到的人而言 .
 
其实他电话还没打完 , 我就知道问题 99% 是他的 jsp 在编辑的时候是存为 UTF-8 而不是 ANSI 格式 , 否则没有道理出现这种问题 , 事实正是如此 , 我让他用 UE 打开看看果然前面多了几个 UTF 字符 .
 
重要的是 TOMCAT 这种容器竟然有这样的 BUG, 不能正确读取 UTF-8 格式的文件 , 你总不能强求用户编辑 JSP 文件时一定要存为什么格式吧 ?
费话少说 , 下载 tomcat5 src, 进入
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler
找到 JspUtil.java
找到
public static InputStream getInputStream(String fname, JarFile jarFile,
     JspCompilationContext ctxt,
     ErrorDispatcher err)
throws JasperException, IOException {
 
        InputStream in = null;
 
if (jarFile != null) {
    String jarEntryName = fname.substring(1, fname.length());
    ZipEntry jarEntry = jarFile.getEntry(jarEntryName);
    if (jarEntry == null) {
err.jspError("jsp.error.file.not.found", fname);
    }
    in = jarFile.getInputStream(jarEntry);
} else {
    in = ctxt.getResourceAsStream(fname);
}
 
if (in == null) {
    err.jspError("jsp.error.file.not.found", fname);
}
return in;
    }
 
在return in前加上判断,改成:
    public static InputStream getInputStream(String fname, JarFile jarFile,
     JspCompilationContext ctxt,
     ErrorDispatcher err)
throws JasperException, IOException {
 
        InputStream in = null;
 
if (jarFile != null) {
    String jarEntryName = fname.substring(1, fname.length());
    ZipEntry jarEntry = jarFile.getEntry(jarEntryName);
    if (jarEntry == null) {
err.jspError("jsp.error.file.not.found", fname);
    }
    in = jarFile.getInputStream(jarEntry);
} else {
    in = ctxt.getResourceAsStream(fname);
}
 
if (in == null) {
    err.jspError("jsp.error.file.not.found", fname);
}
PushbackInputStream testin = new PushbackInputStream(in);
int ch = testin.read();
if (ch != 0xef) {
testin.unread(ch);
    }
    else if ((ch = testin.read()) != 0xbb) {
 testin.unread(ch);
 testin.unread(0xef);
    }
    else if ((ch = testin.read()) != 0xbf) {
      throw new IOException(" 错误的UTF-8格式文件");
    }
    else{
      //fStream.setEncoding("UTF-8");
         testin.read();
    }
return testin;
    }
 
编译 , 重新打包 , 替换原来的包 , 运行 TOMCAT,OK!
 
整个问题解决除了远程登录他的服务器传送文件的时间 , 总共只有 4-5 分钟 . 其实只要问题定位准确 , 就不难解决了 . 我一再强调的是经熟悉底层 , 你如果知道内存中每个 byte 从哪儿来要到哪儿去 , 就可以非常容易地解决问题 . 在此之前我连 TOMCAT5 下载都没有下过 , 更别说试用了 . 但只要你对 JDK 有深入的了解 , 就可以准确地定位问题的所在 .
 
希望本文能给不是高手的朋友一点帮助和启发 , 对于高手的朋友你可以弃之一笑
原文地址:
使用FileUpload组件上传文件?
文件上传在 web 应用中非常普遍,要在 jsp 环境中实现文件上传功能是非常容易的,因为网上有许多用 java 开发的文件上传组件,本文以 commons-fileupload 组件为例,为 jsp 应用添加文件上传功能。
common-fileupload 组件是 apache 的一个开源项目之一,可以从 http://jakarta.apache.org/commons/fileupload/ 下载。用该组件可实现一次上传一个或多个文件,并可限制文件大小。
下载后解压 zip 包,将 commons-fileupload-1.0.jar 复制到 tomcat webapps/ 你的 webapp/WEB-INF/lib/ 下,目录不存在请自建目录。
新建一个 servlet: Upload.java 用于文件上传:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;
 
public class Upload extends HttpServlet {
 
    private String uploadPath = "C://upload//"; // 上传文件的目录
    private String tempPath = "C://upload//tmp//"; // 临时文件目录
 
    public void doPost(HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException
    {
    }
}
doPost() 方法中,当 servlet 收到浏览器发出的 Post 请求后,实现文件上传。以下是示例代码:
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
    try {
        DiskFileUpload fu = new DiskFileUpload();
        // 设置最大文件尺寸,这里是4MB
        fu.setSizeMax(4194304);
        // 设置缓冲区大小,这里是4kb
        fu.setSizeThreshold(4096);
        // 设置临时目录:
        fu.setRepositoryPath(tempPath);
 
        // 得到所有的文件:
        List fileItems = fu.parseRequest(request);
        Iterator i = fileItems.iterator();
        // 依次处理每一个文件:
        while(i.hasNext()) {
            FileItem fi = (FileItem)i.next();
            // 获得文件名,这个文件名包括路径:
            String fileName = fi.getName();
            // 在这里可以记录用户和文件信息
            // ...
            // 写入文件,暂定文件名为a.txt,可以从fileName中提取文件名:
            fi.write(new File(uploadPath + "a.txt"));
        }
    }
    catch(Exception e) {
        // 可以跳转出错页面
    }
}
如果要在配置文件中读取指定的上传文件夹,可以在init()方法中执行:
public void init() throws ServletException {
    uploadPath = ....
    tempPath = ....
    // 文件夹不存在就自动创建:
    if(!new File(uploadPath).isDirectory())
        new File(uploadPath).mkdirs();
    if(!new File(tempPath).isDirectory())
        new File(tempPath).mkdirs();
}
 
编译该 servlet ,注意要指定 classpath ,确保包含 commons-upload-1.0.jar tomcat/common/lib/servlet-api.jar
配置 servlet ,用记事本打开 tomcat/webapps/ 你的 webapp/WEB-INF/web.xml ,没有的话新建一个。
典型配置如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
 
<web-app>
    <servlet>
        <servlet-name>Upload</servlet-name>
        <servlet-class>Upload</servlet-class>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>Upload</servlet-name>
        <url-pattern>/fileupload</url-pattern>
    </servlet-mapping>
</web-app>
配置好servlet后,启动tomcat,写一个简单的html测试:
<form action="fileupload" method="post"
enctype="multipart/form-data" name="form1">
 <input type="file" name="file">
 <input type="submit" name="Submit" value="upload">
</form>
 
 
注意 action="fileupload" 其中 fileupload 是配置 servlet 时指定的 url-pattern
 
原文地址:
 
session 中存放数据库 connection 的问题
我在程序中设置 bea scope="session" ,可是总出以下警告,程序可以正常执行
<2004-6-14
下午 16 23 55 CST> <Warning> <HTTP Session> <BEA-100061> <Web application: ServletContext(id=8782613,name=DefaultWebApp,context-path=) tried to pl
ace a non-serializable attribute: conn into the session: ANgbIJn2Rb719Kv0AlCpckp
irYkwOSzHw2Ypte1STZ2VH92Nuttb!-2121598438!1087201435515. This attribute will be
lost upon redeployment. This message is logged only once per session.>
 
这是因为这个 conn 对象不可以串行化,如这样会出现警告信息。
 
原文地址:
 
 
如果防止 JSP页面刷新
J2EE 核心模式》中提到避免重复提交的方法是使用令牌( token ),在生成修改页面的同时生成一个 token ,把它放在表单( form )的一个隐藏域里,并且把它放在 session 属性中。用户提交表单的时候,比较 form token session 中的 token 是否一样,如果一样,修改 session 中的 token (如果用户刷新,两个 token 就不一样),然后执行操作;如果不一样那就是重复提交的表单,不执行。
 
原文地址:
 
JSP I/O 方面的一些问题
这和容器的实现方式有关系,因为在 JSP 中一般不直接操作二进制输出流,一般的容器在解释 JSP 标签时,每一行都加入一个 " ", :
<%OutputStream.write(byte[] b1)%>
<%OutputStream.write(byte[] b2)%> 这样在连续的二进制流中就多了一个空格 , 肯定没有用了 . 当然象
<%@page .....%>
<jsp:useBean ......../>
这类的标签肯定在每一行加了 " ", 也就是调用了 Writer 接口的 println 方法 . 你看连那个老外写的 jspSmartUpload 的例子中 , 他穷极无奈只好把 <%pag....e%>< jsp:useBean../><%%> 写在一行上 , 一旦分开,下载的例子中下载的文件就不对了。
 
有些容器在实现时如果要输出二进制文件是 , 会自动清空输出流 , 也就是把原来缓冲中 Writer 子类写的文本流清空 , 然后输出二进制流以保证数据的正确性和完整性 , 这是 " 人情 ", 因为规范没有要求这么做 , 所以如果不能自动重设你也不能说它不对 , 这叫 " 本份 ". 你只有手要调用 , 其实很简单 ,
response.setContentType () , 自己把文本流先清空就行了 . 因为容器在解释 JSP 文件前 , 只要看到是这个编译后的 servlet 是实现 HttpJspPage 接口 , 那就肯定先 setContentType ("text/html"), 你在调用是 setContentType ("image/png") 其实是在改变输出流类型 , 所以应该先空 response buffer, 方法就是一句话 ;response.reset(); 放在 setContentType ("image/png"); 前面啊 .
 
我这样解释不知道你明白了没有 , 其实在任何调用二进制输出流时都应该调用这一句 , 不管容器有没有先调用 , 你再调用一次也没有关系 .
 
原文地址:
 
文件下载的时候为什么 finally里面的代码没有执行?
 
正常下载完毕可释放资源,可下载中途取消就不行了,我用 finally 也不行,点取消按钮后, finally 内的代码并没有执行,只有页面时它才认为程序需要关闭而执行 finally 内的代码;
 
程序如下:
<%
InputStream inStream=null;
try{ inStream=new FileInputStream("/download/"+id);
// 设置输出的格式
 response.reset();
 response.setContentType("bin");
 response.addHeader("Content-Disposition","attachment;filename");
// 循环取出流中的数据
 byte[] b = new byte[100];
 int len;
 while((len=inStream.read(b))>0)
 response.getOutputStream().write(b,0,len);
 inStream.close();
 response.getOutputStream().close();
}catch(IOException e){
    System.out.println(e.getMessage());
}finally {
     try{
           System.out.println(" 取消下载");
        if(inStream!=null)inStream.close();
         response.getOutputStream().close();                   
     }catch(Exception e){   
        System.out.println(e.getMessage());
     }
}
%>
 
 
 
java 60 多种 Stream 操作 , 并不是可能拿来互用的 , 要不 SUN 开发小组没事干了啊 , 每一种流在处理不同的数据有不同的效率 , 大家最好把这些基础的东西的实现源码看一看 , 我可以吹一句 , 对我来说 ,JAVA 平台上可以解决任何乱码 , 数据混乱 , 因为我清楚每个 byte 的来胧去脉 .
 
最简单的一个例子 :new PrintWriter(new FileWriter(path,true),true);
大家都清楚这两个 true 有什么作用吗 ? 当然第一个简单 ,true 表示追加而不是履盖原文件 , 第二个呢 ? 大家知道是自动 flush? 那为什么要用参数控制而不在实现时就 flush? 只有 java 是这么实现的 ,C/C++ 就是自动 flush . 原因何在 ?
 
因为 JAVA 委托系统调用要极度消耗资源的 , 如果每次 println 都真的写文件 , 则用户模式和内核模式之间的切换要消耗极大的资源 , 所以先放在缓冲中 , 当调用 close() 时或 OBU 时一次调用 jini, 请系统写文件 . 但如果 PrintWriter 作为管道流 , 也就是象 Socket 这种通讯时即时性比性能更重要 , 所以要有手工控制的参数 .
 
这些都是作为网络编程的基础知识 , 我本来不想多说 . 象为什么取消下载资源不能回收这种情况 , 其实你想一想 , 客户端事件是否被服务端接收 ? 就是接收了也绝对不会在一个流输出的进程中接收的 , 因为 HTTP 是无状态的 , 除非你的 servlet 就实现这个这种监听 , 不然你在客户端取消 , 只是容器不把 response 对象的 buffer 数据再发给你 , service() 方法本身你不能控制它执行什么 , 要么容器智能一点取消这个方法的执行 ( 杀掉线程池中的线程 ID), 而不会让这个方法中的代码产生异常 .
 
原文地址:
 
请问 web server怎么将配置文件参数在web application启动的时候读进内存
很多第三方的 api 都是这么做的。比如 struts ,就是在 web app 启动的时候,将 struts-config.xml 中的信息写入内存对象。
 
下面就提供一种其中的时候,读取 web-inf 目录下 test.xml 配置文件内容的代码,异供参考。
 
web.xml 配置如下:
 <servlet>
    <servlet-name>ConfigServlet</servlet-name>
    <servlet-class>net.test.ConfigServlet</servlet-class>
    <init-param>
      <param-name>configfile</param-name>
      <param-value>/WEB-INF/test.xml</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
   </servlet>
 
代码如下:
public class ConfigServlet extends HttpServlet {
 
 protected final Locale defaultLocale = Locale.getDefault();
 
 public void init() throws ServletException {
    try{
      initConfigXML();
    }catch(Exception e){
      System.out.println("ERROR >>> 读取riseconfig.xml文件出现问题");
    }
 }
 
 protected void initConfigXML() throws IOException, SAXException,ServletException,Exception{
    String value = null;
    RiseConfig rcObject = null;
 
    value = getServletConfig().getInitParameter("configfile");
 
    InputStream input = getServletContext().getResourceAsStream(value);
 
    // 剩下的就不要写了,自己处理了。
 
 }
 
}
 
原文地址:
 
你的环境变量可能是为 web 应用、 ejb 使用的。
WebDescriptor>Web App Descriptor>Parameters 里配置:
 <context-param>
    <param-name>PATH</param-name>
    <param-value>C:/GWSSI/INVOICE/PDF</param-value>
 </context-param>
当然只能在 web 应用里才能获得:( jsp 里的例子)
String strPath=config.getInitParameter("PATH");
 
ejb FPGL_FWSK.jar> EJB Jar> Enterprise Beans> Sessions> InvoiceReturnBean> Environment Entries 里, Configure a new Environment Entry... 也可以配置供这个 ejb 使用的环境变量:
 <env-entry>
                <description />
                <env-entry-name>DBLanguage</env-entry-name>
                <env-entry-type>java.lang.String</env-entry-type>
                <env-entry-value>American</env-entry-value>
            </env-entry>
当然只能在ejb里才能获得:
    public String getDbLanguage()
        throws NamingException
    {
        Context initial = new InitialContext();
        return (String)initial.lookup("java:comp/env/DBLanguage");
    }
 
 
至于普通的客户端,怎么得到wls环境变量,那首先应该加载wls变量:
 
try{
 Properties p=System.getProperties();
 Enumeration e=p.propertyNames();
 String strPropertyName;
 while (e.hasMoreElements()) {
 strPropertyName=(String)e.nextElement();
        out.println(strPropertyName+":"+System.getProperty(strPropertyName));
 }
}catch(Exception e){
   out.println(e.getMessage());
}
另外可以这样:
web.xml
 
<context-param>
     <param-name>dev2dev.bea.com.cn</param-name>
     <param-value>211.157.35.33</param-value>
</context-param>
 
usage:
Servlet Context ctx=getServletContext();
out.print("dev2dev.bea.com.cn 的Server ip地址是:");
out.print(ctx.getInitParameter("dev2dev.bea.com.cn"));
 
 
原文地址:

前台表现层 JFreeReport生成PDF报表
下面是我的研究成果 . 希望对你有所帮助 :
报表生成一直是企业信息化过程中重要的一环,也是目前比较难于实现的一环,今天作者给大家介绍一种新的报表生成组件 ――JFreeReport JFreeReport JFreeReport.Org 基于 LGPL 授权协议提供的一组 java 包,用于生成各类报表, JFreeReport 的数据继承自 Swing 组件的 TableModel 接口,使用基于 XML 的报表格式定义文件对报表进行格式化。 JFreeReport 生成的报表可以分页预览、打印,而且支持导出为多种格式的文件如 pdf Excel CSV html 等。更重要的是, JFreeReport 不仅支持基于 C/S 结构的系统,而且支持基于 B/S 结构的系统中的在线报表显示。更详细的关于 JFreeReport 的介绍请大家访问 JFreeReport 的官方网站 JFreeReport.org
 
1 环境准备
1.1 JFreeReport 组件
请大家到 http: //prdownloads.sourceforge.net/jfreereport/jfreereport-0.8.4_7.zip?download 下载 JFreeReport 组件,下载的是一个 ZIP 文件,然后将 ZIP 文件解压缩到 c:/jfreereport (后面的章节中将使用% jfreereport_home %表示这个目录)目录下。
1.2 JFreeReport 扩展组件
请大家到 http: //www.jfree.org/jfreereport/jfreereport-ext-0.8.4_7.zip 下载 JFreeReport 扩展组件,他用于支持 JFreeReport 组件生成的报表的在线显示。请大载后解压缩到 c:/jfreereport-ext 目录下(后面的章节中将使用% jfreereport_ext_home %表示这个目录)
1.3 Ant 工具
Apache 公司提供的一个基于 JAVA 的自动化脚本引擎,请大家到 http://ant.apache.org/ 下载 ant 的可执行文件,关于如何使用 ant 请大家查看 ant 的帮助文档或者 http://ant.apache.org/ 网站上的在线帮助文档。示例中主要是用 ant 来负责编译 java 代码。
1.4 作者提供的代码
为了运行本文中作者提到的例子和相关资源文件,请大家下载作者提供的 vivianjDemo.zip 文件。然后解压缩到% jfreereport_home /vivianjDemo (后面的章节中将使用% demo _home %表示这个目录)目录下。
2 JFreeReport 生成报表的基本步骤
我们首先演示一个简单的例子,说明使用 JFreeReport 生成报表的一些必要的步骤。
2.1 实例说明
在这个例子中,我们将循环生成 100 条数据放入 TableModel 中,然后使用 JFreeReport 组件提供的预览功能在屏幕上显示生成的报表。
[注]为了简化,这里仅仅是逐条显示数据,不作任何修饰和统计工作,所以也不使用报表格式定义文件。
2.2 代码编制
整个演示实例( HelloWorld.java )的代码和相关注释如下,如果你执行了 1.3 中规定的步骤,你可以在% demo _home %/ src org/vivianj/jfreereport/ 看到这个文件。
/**
* HelloWorld.java
*/
 
package org.vivianj.jfreereport;
 
import java.awt.Color;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Point2D;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
 
import org.jfree.report.Boot;
import org.jfree.report.ElementAlignment;
import org.jfree.report.JFreeReport;
import org.jfree.report.ReportProcessingException;
import org.jfree.report.elementfactory.TextFieldElementFactory;
import org.jfree.report.modules.gui.base.PreviewDialog;
import org.jfree.ui.FloatDimension;
 
/**
* 使用JFreeReport生成报表的简单例子,用于演示使用JFreeReport生成报表的一些基本步骤
*
* 本例子中,为了简化操作,报表定义是使用java直接编码
*
* @ 作者 : bookman
*/
public class HelloWorld
{
 /**
   * 处理窗口关闭事件
   */
 protected static class CloseHandler extends WindowAdapter
 {
    public void windowClosing(final WindowEvent event)
    {
      System.exit(0);
    }
 }
 
 /**
   * 创建和显示简单的报表
   */
 public HelloWorld()
 {
// 获得创建报表需要用到的数据
    final TableModel data = createData();
// 获得报表要用到的报表定义内容
    final JFreeReport report = createReportDefinition();
// 将报表定义和数据结合
    report.setData(data);
    try
    {
 // 将生成的报表放到预览窗口中
      final PreviewDialog preview = new PreviewDialog(report);
      preview.addWindowListener(new CloseHandler());
      preview.pack();
 // 显示报表预览窗口
      preview.setVisible(true);
    }
    catch (ReportProcessingException e)
    {
      System.out.println(e);
    }
 
 }
 
 /**
   * 创建生成报表需要用到的数据
   *
   * @ 返回一个TableModel实例
   */
 private TableModel createData()
 {
 
    final Object[] columnNames = new String[]{"Column1", "Column2"};
    final DefaultTableModel result = new DefaultTableModel(columnNames, 100);
int rownum = 0;
int colnum = 0;
for (;rownum < 100 ; rownum++)
{
result.setValueAt("say Hello " + rownum + " 次", rownum, 0);
result.setValueAt("say World " + rownum + " 次" , rownum, 1);
}
 
    return result;
 
 }
 
 /**
   * 创建一个报表定义
   *
   * @ 返回一个报表定义实例
   */
 private JFreeReport createReportDefinition()
 {
 
    final JFreeReport report = new JFreeReport();
    report.setName("A Very Simple Report");
/**
 * 定义要显示报表第一列的样式
*/
    TextFieldElementFactory factory = new TextFieldElementFactory();
    factory.setName("T1");
    factory.setAbsolutePosition(new Point2D.Float(0, 0));
    factory.setMinimumSize(new FloatDimension(150, 20));
    factory.setColor(Color.black);
    factory.setHorizontalAlignment(ElementAlignment.LEFT);
    factory.setVerticalAlignment(ElementAlignment.MIDDLE);
    factory.setNullString("-");
    factory.setFieldname("Column1");
    report.getItemBand().addElement(factory.createElement());
/**
 * 定义要显示报表第二列的样式
*/
    factory = new TextFieldElementFactory();
    factory.setName("T2");
    factory.setAbsolutePosition(new Point2D.Float(200, 0));
    factory.setMinimumSize(new FloatDimension(150, 20));
    factory.setColor(Color.black);
    factory.setHorizontalAlignment(ElementAlignment.LEFT);
    factory.setVerticalAlignment(ElementAlignment.MIDDLE);
    factory.setNullString("-");
    factory.setFieldname("Column2");
    report.getItemBand().addElement(factory.createElement());
/**
 * 返回一个报表定义的实例
*/
    return report;
 
 }
 
 public static void main(final String[] args)
 {
    // 初始化JFreeReport
    Boot.start();
 
    // 调用演示实例
    new HelloWorld();
 }
 
}
 
 
2.3 运行例子
如果你执行了 1.3 中规定的步骤,你可以进入命令行界面,然后进入% demo_home %目录下,修改 setenv.cmd 中的相关设置,执行 serenv.cmd 设置环境变量。执行 java org.vivianj.jfreereport.HelloWorld 查看运行结果。下面这个图片是作者执行后结果的屏幕截图:
 
大家可以看到, JFreeReport 已经自动帮我们实现了分页。上面这个图片显示的是第一页的数据,你可以通过工具栏中的查看其它页面中的内容。
2.4 基本步骤解释
使用 JFreeReport 生成报表通常需要以下三个基本步骤:
1. 生成可通过 TableModel 接口访问的数据,如本例中的 createData 方法完成的功能
2. 生成一个 JFreeReport 实例,他定义了我们如何格式化显示数据,如本例中的 createReportDefinition 方法完成的功能
3. 将数据和 JFreeReport 实例连接起来,并且将该 JFreeReport 实例传给 PreviewDialog 的一个实例显示给用户
 
3 使用 JFreeReport 生成复杂报表
3.1 报表定义文件
报表定义文件是 JFreeReport 生成复杂报表的重要文件,他就是一个 XML 文档,主要描述如何使用指定的格式生成复杂的报表,同时使用报表定义文件也可以在报表格式需要修改时只需要更新该报表定义文件,而不需要修改应用代码。
 
3.1.1 报表定义文件分类
JFreeReport 中使用了两种基于 XML 的报表定义文件来保存报表定义信息:简单格式和扩展格式.很明显 , 简单格式不能够完全的描述 JFreeReport 支持的全部报表定义信息 , 但是他更易于上手使用。而扩展格式则能够对 JFreeReport 的报表定义提供完整的支持,但是扩展格式太详细了,不太容易使用。
 
关于这两种报表定义格式文件所支持的标签内容以及如何编写这两种格式的报表定义文件请大家参考% jfreereport_home %下的 jfreereport-0.8.3-A4.pdf 中的相关部分,该文件附录中还包括了这两种格式的报表定义文件的 DTD 文档供大家参考.当然大家也 JFreeReport 的例子中提供了多种形式的报表定义文件,基本上涵盖了常用的报表格式定义,大家可以参考这些例子编写自己的报表定义文件,。
3.2 代码编制
这个例子和 2.2 中的代码基本一致,只是报表定义内容不再由 java 编码实现,而是由报表定义文件提供,所以调用方面稍微有点不同,详细的代码如下,请大家注意其中加粗显示的部分:
/**
* JFreeReport.java
*/
 
package org.vivianj.jfreereport;
 
import java.io.File;
import java.text.MessageFormat;
import javax.swing.table.TableModel;
import javax.swing.JFrame;
 
import org.jfree.ui.RefineryUtilities;
import org.jfree.report.Boot;
import org.jfree.report.modules.gui.base.PreviewFrame;
import org.jfree.report.modules.parser.base.ReportGenerator;
import org.jfree.report.JFreeReport;
 
import org.vivianj.jfreereport.tablemodel.SampleData;
 
/**
* 使用JFreeReport生成复杂报表的例子,用于演示使用JFreeReport生成复杂报表的一些基本步骤
*
* 本例子中,报表定义使用了报表定义文件,该文件是保存在c:\下的report3.xml文件
* 本例中使用的报表定义使用了简单报表定义格式
*
* @ 作者 : bookman
*/
public class JFreeTest
{
 
public JFreeTest(final String urlname, final TableModel data)
 {
// 创建对报表定义文件的引用
    final File in = new File(urlname);;
    if (in == null)
    {
      System.out.print(" in is null");
      return;
    }
 
    System.out.print("Processing Report: " + in);
    final ReportGenerator gen = ReportGenerator.getInstance();
 
    try
    {
      // 从报表定义文件中获得要用到的报表定义内容
      final JFreeReport report1 = gen.parseReport(in);
      if (report1 == null)
      {
        System.out.print(" report1 is null");
        return;
      }
      // 将报表定义和数据结合
      report1.setData(data);
 // 将生成的报表放到预览窗口中
      final PreviewFrame frame1 = new PreviewFrame(report1);
      frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame1.pack();
      RefineryUtilities.positionFrameRandomly(frame1);
      frame1.setVisible(true);
      frame1.requestFocus();
    }
    catch (Exception e)
    {
      System.out.print("report.definitionfailure-----------------------/r/n" + e);
    }
 }
 
 
 public static void main(String[] args)
{
Boot.start();
 
final TableModel data3 = new SampleData();
JFreeTest jft = new JFreeTest("c://report3.xml",data3);
}
}
4 中文乱码问题
大家在参看报表定义文件的时候会发现,里面的报表头定义中有一些显示内容,如果你直接将他修改成中文,显示在报表上就会乱码,这是因为这些报表定义文件都是 XML 文档,他的 encoding 默认设置是 ISO-8859-1 ,所以出现了中文乱码的问题,解决办法有两个:
1. 最简单的方法就是将 encoding 的设置修改为 GB2312
2. 还有一个方法就是不修改 encoding 的设置,而是将这些中文内容使用他们的 unicode 码来代替。
[注]作者提供了一个 GUI 的界面提供这种转化功能,你只需要输入中文就可以获得对应的 unicode 码,请大家下载作者提供的 gb2unicode.jar ,设置好 java 运行环境,然后执行 java –jar gb2unicode.jar 就可以了。
 
原文地址:
 
 
POI 介绍
介绍 :
Jakarta_POI 使用 Java 读写 Excel(97-2002) 文件,可以满足大部分的需要。
因为刚好有一个项目使用到了这个工具,花了点时间顺便翻译了一下 POI 本身
带的一个 Guide. 有一些节减和修改,希望给使用这个项目的人一些入门帮助。
POI 下面有几个自项目 :HSSF 用来实现 Excel 的读写 . 以下是 HSSF 的主页
http://jakarta.apache.org/poi/hssf/index.html
下面的介绍是基于以下地址的翻译:
http://jakarta.apache.org/poi/hssf/quick-guide.html
目前的版本为 1.51 应该是很长时间之内的一个稳定版,但 HSSF 提供的 Sample 不是基于
1.51 所写,所以使用的时候需要适当的注意 .
其实 POI 下面的几个子项目侧重不同读写 Word HDF 正在开发当中 .
XML 下的 FOP(http://xml.apache.org/fop/index.html)
可以输出 pdf 文件,也是比较好的一个工具
目录 :
创建一个 workbook
创建一个 sheet
创建 cells
创建日期 cells
设定单元格格式
 
说明:
以下可能需要使用到如下的类
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
 
创建 workbook
 
HSSFWorkbook wb = new HSSFWorkbook();
// 使用默认的构造方法创建 workbook
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
// 指定文件名
wb.write(fileOut);
// 输出到文件
fileOut.close();
 
创建一个 sheet
 
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet1 = wb.createSheet("new sheet");
//workbook 创建 sheet
HSSFSheet sheet2 = wb.createSheet("second sheet");
//workbook 创建另外的 sheet
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
 
创建 cells
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");
// 注意以下的代码很多方法的参数是 short 而不是 int 所以需要做一次类型转换
HSSFRow row = sheet.createRow((short)0);
//sheet 创建一行
HSSFCell cell = row.createCell((short)0);
// 行创建一个单元格
cell.setCellValue(1);
// 设定单元格的值
// 值的类型参数有多中 double ,String ,boolean,
row.createCell((short)1).setCellValue(1.2);
row.createCell((short)2).setCellValue("This is a string");
row.createCell((short)3).setCellValue(true);
 
// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
 
创建日期 cells
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");
 
HSSFRow row = sheet.createRow((short)0);
 
HSSFCell cell = row.createCell((short)0);
// 设定值为日期
cell.setCellValue(new Date());
 
HSSFCellStyle cellStyle = wb.createCellStyle();
// 指定日期显示格式
cellStyle.setDataFormat(HSSFDataFormat.getFormat("m/d/yy h:mm"));
cell = row.createCell((short)1);
cell.setCellValue(new Date());
// 设定单元格日期显示格式
cell.setCellStyle(cellStyle);
 
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
 
 
设定单元格格式
单元格格式的设定有很多形式包括单元格的对齐方式,内容的字体设置,
单元格的背景色等,因为形式比较多,只举一些例子 . 以下的例子在
POI1.5 中可能会有所改变具体查看 API.
..........
// Aqua background
HSSFCellStyle style = wb.createCellStyle();
// 创建一个样式
style.setFillBackgroundColor(HSSFCellStyle.AQUA);
// 设定此样式的的背景颜色填充
style.setFillPattern(HSSFCellStyle.BIG_SPOTS);
 
// 样式的填充类型。
// 有多种式样如 :
//HSSFCellStyle.BIG_SPOTS
//HSSFCellStyle.FINE_DOTS
//HSSFCellStyle.SPARSE_DOTS
style.setAlignment(HSSFCellStyle.ALIGN_CENTER );
// 居中对齐
style.setFillBackgroundColor(HSSFColor.GREEN.index);
// 设定单元个背景颜色
style.setFillForegroundColor(HSSFColor.RED.index);
// 设置单元格显示颜色
HSSFCell cell = row.createCell((short) 1);
cell.setCellValue("X");
cell.setCellStyle(style);
 
原文地址:
 
 
使用 POI创建Excel格式数据
目前为止,在 Java 应用程序中建立一个 Microsoft Excel 文件的最常用的方法是在 JSP Servlet 中创建一个 CSV comma separated values )文件,并将这个文件以 MIME text/csv 类型返回给浏览器。接着浏览器调用 Excel 并且显示 CSV 文件。
 
现在有一个提供实用工具给 Java 开发者建立 Excel 文件的项目,该项目是 POI (Poor Obfuscation Implementation ) Jakarta 工程中最成熟的一部分。 POI Excel 组件名叫 HSSF (Horrible Spreadsheet format)
 
虽然 HSSF 提供了许多与开发工具交互的不同方法,我们这里只集中讨论简单高级用户 API
下面是一个在 Excel 表格中创建矩阵的简单例子:
 
import org.apache.poi.hssf.usermodel.*;
import java.io.FileOutputStream;
 
 
// code run against the jakarta-poi-1.5.0-FINAL-20020506.jar.
 
public class PoiTest {
 
static public void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("foo.xls");
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet s = wb.createSheet();
wb.setSheetName(0, "Matrix");
for(short i=0; i<50; i++) {
HSSFRow row = s.createRow(i);
for(short j=0; j<50; j++) {
HSSFCell cell = row.createCell(j);
cell.setCellvalue(""+i+","+j);
}
}
wb.write(fos);
fos.close();
}
}
这段代码首先创建一个业务手册,从这个业务手册中获取一个表格,给这个表格命名,然后接着在上面写一个 50*50 的矩阵列表。它的输出是一个名为 foo.xls Excel 文件,这个文件即使在 Apple Mac 上也可以打开。
POI 工程是 Java 走出的振奋人心的,全新的一步,它为 Windows 的文件综合开辟了一个新的领域,并且使得 Java 开发者能够改进他们的产品功能。
 
原文地址:

应用服务器特殊问题 Tomcat 中的 Web 应用迁移到 Weblogic 8.1
今天把原来部署在 Tomcat 中的 Web 应用程序迁移到 Weblogic 8.1 中文版上面了 . 基本上没什么大问题 , 就是有几句只适用于 Tomcat 的代码需要修改一下 . 在这里记录下来 , 可能以后还会碰到 .
 
1 、载入属性文件问题 :
属性文件包括 db.properties mail.properties 等。上述属性文件放在 WEB-INF 目录底下,原来采用 DbContext.class.getClassLoader().getResourceAsStream("../db.properties") 取得输入流 InputStream is 。对 Tomcat 来说, DbContext.class.getClassLoader() 应该是对应 classes 目录,采用 “../” 回到上层目录,就是 WEB-INF 目录,这个是可行的。而 Weblogic 好象不支持 “../” ,老是提示找不到相应的属性文件。不得已,只好将属性文件放到 classes 目录下。上述代码改为: DbContext.class.getClassLoader().getResourceAsStream ("db.properties")
 
2 、取得文件绝对路径问题:
在上传下载功能中,经常设计到要取得相应文件或者文件夹的绝对路径问题。这里通常采用 getServletContext().getRealPath("yourFile") 方法。 Tomcat 中可以直接用。而 Weblogic 要采用 getServletConfig().getServletContext().getRealPath ("/upload") 。同事说是两者对 Servlet 的实现不同。
 
原文地址:
 
weblogic7.0 中怎样实现定时执行程序 ?
应该采用 listener, 在其中实现一个 Timer 即可,我已经说了实现 listener , 你可能只想到普通的 listener,servlet 为我们提供了三种模式 ,stand,listener,filter, 只要实现一个 listener OK 了啊。
public class MyListener
    extends HttpServlet
    implements ServletContextListener {
 private static Timer timer;
 
 public void contextInitialized(ServletContextEvent sce) {
    timer = new Timer(true);
    timer.schedule(new TimerTask() {
      public void run() {
         要定时执的代码
      }
    }, argslist........);
 
 }
 public void contextDestroyed(ServletContextEvent sce) {
    timer.cancel();
 }
}
你可以完成你想做的任何事
 
原文地址:
养成使用在 web.xml里配置引用资源的习惯
比如你创建了一个 DataSource MyTestDataSource ),绑定 MyTestConnectionPool ,绑定 MyTestDataSourceJNDI 命名。但是却想在程序中采用 MyDataSource 这个 JNDI 名称。你就需要修改 web.xml weblogic.xml
web.xml 修改如下
 <resource-ref>
    <res-ref-name>MyDataSource</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Application</res-auth>
 </resource-ref>
 
weblogic.xml 修改如下
 <reference-descriptor>
    <resource-description>
      <res-ref-name>MyDataSource</res-ref-name>
      <jndi-name>MyTestDataSourceJNDI</jndi-name>
    </resource-description>
 </reference-descriptor>
 
 
原文地址:
 
关于 web-inf下的JSP的引用问题
把一个 include.jsp 文件放到目录 WEB-INF 里面,然后使用
  String url = "/WEB-INF/include.jsp";
      RequestDispatcher rd = pageContext.getRequest().getRequestDispatcher(url);
      rd.include(pageContext.getRequest(), pageContext.getResponse());
      url));
总是抛出未找到资源异常,这是怎么回事啊。
 
这好像是 WebLogic 以前的一个问题,由于 WEB-INF 里面的内容对于 WEB 应用而言,都是至关重要的配置文件和类,所以,出于安全考虑, J2EE 规范对于 WEB-INF 目录是拒绝外部访问的,里面的内容,只允许 Container 访问。
 
规范原文如下:
No file contained in the WEB-INF directory may be served directly to a client by the container. However, the contents of the WEBINF directory are visible to servlet code using the getResource and getResource-AsStream method calls on the ServletContext, and may be exposed using the RequestDispatcher calls.
 
原文地址:
WebLogic7 关于 JSP 编译的一个 BUG
wls7.0 里部署了一个 web 应用,每次重起 wls 后, jsp 文件都会被重新编译,如何设置,才能只让编译一次 ?
 
wls7.0 里面,再没有特别的指明情况下,自定义的 web 应用会将 web 编译完的 jsp 文件存储在 user_projects/mydomain/applications/.wlnotdelete 目录下。但是 wls7.0 犯了一个错误,在每一次启动的时候,会将 user_projects/mydomain/applications/.wlnotdelete 目录下的文件清空。这就造成了,上次 jsp 编译成的 .class 文件就被删除了。所以,每次重新启动 wls 以后,就造成 jsp 重新编译。
 
那么如何解决这个问题了。很简单的了。在 weblogic.xml 文件中的 <jsp-descriptor> 元素下,加一个
<jsp-param>
<param-name>workingDir</param-name>
<param-value>workingDir</param-value>
</jsp-param>
这样以后,强迫每次编译后的 jsp 存储在 user_projects/mydomain/workingDir/jsp_servlet 目录下。这样每次重新启动以后,就不需要重新编译了。
 
 
原文地址:
 
如文件为 doc ,在 WEB.XML 文件里加入
  <mime-mapping>
  <extension>doc</extension>
  <mime-type>application/self-define</mime-type>
  </mime-mapping>
就可以出现提示下载框了 ,application/self-define" 不需要修改 , 因为注册表里没有对应的 application/self-define 内容。
 
原文地址:
 
weblogic6.1下调试时如何保留系统编译jsp文件所生成的.java文件?
请参考 weblogic doc 中的 webapp 文档。
其中在 weblogic.xml Deployment Descriptor Elements 章节有说明。参考 jsp-descriptor Element 描述说明。其中一个元素
元素: keepgenerated
默认值: false
说明: Saves the Java files that are generated as an intermediary step in. he JSP compilation process.Unless this parameter is set to true,the intermediate Java files are deleted after they are compiled.
原文地址:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值