关闭

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

标签: java报表servletequalsimportstring
2492人阅读 评论(0) 收藏 举报
分类:
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.简述synchronizedjava.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.utiljava.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: 两种形式 dtdschema
b: 本质区别:schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema
根本目的)
c: 两种主要方式:domsax.答出两种得全分,如能答出saxt,或其它(在答出domsax的基
础上,如果应试者认为其它方式也可以视为对xml的解析应该允许.但没有答出domsax
其它方式说成是对XML的解析不得分)应该加分.
 
5.简述synchronizedjava.util.concurrent.locks.Lock的异同?(15)
 
主要相同点:
Lock能完成synchronized所实现的所有功能.(其它不重要)
主要不同点:
Lock有比synchronized更精确的线程语义和更好的性能(在相同点中回答此点也行)
synchronized会自动释放锁.Lock一定要求程序员手工释放.并且必须在finally从句
中释放,如果没有答出在finally中释放不得分.就如Connection没有在finally中关闭一
.连最基本的资源释放都做不好,还谈什么多线程编程.
 
6.EJB规范规定EJB中禁止的操作有哪些?(15)
共有8点,答出下列3-4点得满分.
 
·             不能操作线程和线程API(线程API指非线程对象的方法如notifywait)
·             不能操作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;
}
原文地址:
 
 
axmanequal的深入研究
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成立再oo1没有改变的情况下以后的任何次调用
都成立.
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);
    }
 
 
这是JDKjava.text.FieldPosition的标准实现,似乎没有什么可说的.
 
我信相大多数或绝大多数程序员认为,这是正确的合法的equals实现.毕竟它是JDKAPI实现啊.
 
还是让我们以事实来说话吧:
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中仍然有很多实现是正
确的,如果一个classfinal的,明知它不可能有子类,为什么不用 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是不
是同一数学值。(事实上JDKAPI中并没有这样做,所以我才说是不恰当的例子)
 
在完成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对象,然后把源图象drawBufferedImage的一定位置,再把BufferedImage编码输出到一个输出流如文件或网页.因为drawImageBufferedImageGraphics对象调用的,一切都在内存中而根本没有可视组件,所以根本没有观察者对象,而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))) ;
大家注意是如果flagflase就只有一个";"也就是什么也不做直接进入下一次循环.
我试过一般画一张新图要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));
}
却只要200MS0.2秒左右就完成了.原来,System.out时要调用BIOS的资源,这时线程要闲置等待,到反而让src资源有了load的时间.于是改成:
    while (!(flag=g.drawImage(src, 0, 0, 240, 320, null))) {
    Thread.currentThread().sleep(1);
}
哈哈,成功了.sleep1,5,10MS没有多大区别,都在200MS左右完成,一般不要再睡更多的时间.
 
所以即使是利己线程的也要看它是否对其它资源的请求,真的应了那句话叫"予人方便,于己方便!"
 
原文地址:
 
GBKGB2312字符集的问题
有的用户比如叫扬璠,或是李珺。就不能正确显示她的名字,而显示一个扬?,?,其他中文没问题,就是这些比较偏怪的中文无法显示。这就是GBKGB2312的区别,你说的那几个字是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/ .
 
 
warjar 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不敬了,ServletRequestWrapperdecode出来,getParameter()方法中直接return new String(b,"GBK")得了.这样省得在XML中配置又不起作用。同样从数据库中如果取得的数据乱码,我们只要把JDBCResultSetdecode出来,把其中的getString(int column)方法中的return new String(b)方法都强行加上"GBK"
 
这样取数据保证正确了,然后再来解决显示的问题,即使你的数据在内存中是正确的,你也指定了正确的字符集参数,仍然不能保证你看到的是正确的,原因是系统知道这个编码是对的,但它没有这种字符集来显示,或你用来显示的字集不对.这就是JSP<%@page contentType="text/html;charset=xxxx"%>的作用,有人以为光这样就正确了,你要知道这句和 response.setContentType("text/html;charset=xxxx");是一样的,只它是告诉浏览器我现在发给你的内容是用xxxx字符集来解释的,只能在从网络上或内存中取得的数据是正确的前提下才有用.现在servet1.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 appFiles页中,<Reload Period>设为1
 
原文地址:
 
Tomcat关于UTF-8JSP文件的BUG
刚才,我都要睡下了,朋友打来电话,他们公司新装了TOMCAT5,然后在编译JSP,INCLUDEJSP都出现了问题.就是编译后被 INCLUDE的地方多了两个"??"而其它正常,而如果手工把被INCLUDE的内容COPY上去测没有问题.
他们的工程师都不知道是什么问题,因为周一要发布出去,所以非常着急.
 
我不知道大家听到这种情况会如何,我知道大多数人比我聪明,你肯定想到了,所以你没有必要再看了.我下面的内容只是对没有想到的人而言.
 
其实他电话还没打完 ,我就知道问题99%是他的jsp在编辑的时候是存为UTF-8而不是ANSI格式,否则没有道理出现这种问题,事实正是如此,我让他用UE打开看看果然前面多了几个UTF字符.
 
重要的是TOMCAT这种容器竟然有这样的BUG,不能正确读取UTF-8格式的文件,你总不能强求用户编辑JSP文件时一定要存为什么格式吧?
费话少说,下载tomcat5src,进入
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复制到tomcatwebapps/你的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.jartomcat/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的问题
我在程序中设置beascope="session",可是总出以下警告,程序可以正常执行
<2004-6-14
下午162355 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属性中。用户提交表单的时候,比较formtokensession中的token是否一样,如果一样,修改session中的token(如果用户刷新,两个token就不一样),然后执行操作;如果不一样那就是重复提交的表单,不执行。
 
原文地址:
 
JSPI/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")其实是在改变输出流类型,所以应该先空responsebuffer,方法就是一句话;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());
     }
}
%>
 
 
 
java60多种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 JFreeReportJFreeReport.Org基于LGPL授权协议提供的一组java包,用于生成各类报表,JFreeReport的数据继承自Swing组件的TableModel接口,使用基于XML的报表格式定义文件对报表进行格式化。JFreeReport生成的报表可以分页预览、打印,而且支持导出为多种格式的文件如pdfExcelCSVhtml等。更重要的是,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%/srcorg/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文件的最常用的方法是在JSPServlet 中创建一个CSV comma separated values)文件,并将这个文件以MIMEtext/csv类型返回给浏览器。接着浏览器调用Excel并且显示CSV文件。
 
现在有一个提供实用工具给Java开发者建立Excel文件的项目,该项目是POI (Poor Obfuscation Implementation )Jakarta工程中最成熟的一部分。POIExcel组件名叫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.xlsExcel文件,这个文件即使在Apple Mac上也可以打开。
POI工程是Java走出的振奋人心的,全新的一步,它为Windows的文件综合开辟了一个新的领域,并且使得Java开发者能够改进他们的产品功能。
 
原文地址:

应用服务器特殊问题Tomcat中的Web应用迁移到Weblogic 8.1
今天把原来部署在Tomcat中的Web应用程序迁移到Weblogic 8.1 中文版上面了.基本上没什么大问题,就是有几句只适用于Tomcat的代码需要修改一下.在这里记录下来,可能以后还会碰到.
 
1、载入属性文件问题:
属性文件包括db.propertiesmail.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,只要实现一个listenerOK了啊。
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里配置引用资源的习惯
比如你创建了一个DataSourceMyTestDataSource),绑定MyTestConnectionPool,绑定 MyTestDataSourceJNDI命名。但是却想在程序中采用 MyDataSource这个JNDI名称。你就需要修改web.xmlweblogic.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.
原文地址:
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:18402次
    • 积分:242
    • 等级:
    • 排名:千里之外
    • 原创:3篇
    • 转载:16篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论