Archive for the ‘JSP编程’ Category

php heredoc和phpwind的模板技术使用方法小结

星期一, 06月 2nd, 2008

在PHPde文档中,只是提到了echo可以使用如下命令输出多行字符串(而且其中de变量被自动替换):
PHP相关代码
[复制此相关代码]CODE:
echo <<<END
This uses the “here document” syntax to output
multiple lines with $variable interpolation. Note
that the here document terminator must appear on a
line with just a semicolon. no extra whitespace!
END;

上面deEND结束符可以自己规定,在Phpwind,使用了“EOT”来结束.但是需要注意de是,这个END必须是在一行de开头才能有效,这其实是Heredoc技术de一个局限性(因为heredoc可以自定义结束符,所以引入了这个问题),在下面会提到.
phpwindde模板文件一般存放在templatewind目录下面,在BBS目录中,使用require语句包含这个模板文件.其实这个模板文件是作为对应dePHP文件de一部分执行de,所以就不需要像PHPLib Template那样需要进行模板解析,然后再执行de过程.
为了让heredocde内容能被DreamWeaver这样de编辑器正确识别,以实现“所见即所得de”de网页设计,需要在heredoc中增加注释,示例文件如下:
PHP相关代码
[复制此相关代码]CODE:
<!–
<?php
print <<<EOT
–>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″ />
<title>Untitled Document</title>
</head>
<body>
<!–
$name = ‘浅水游’;
print <<<EOT
–>
Hello,$name!
<!–
EOT
print <<<EOT
–>
</body>
</html>
<!–
EOT;
?>
–>

这样de模板文件,其实就是一个标准de,可以执行dePHP文件.但是,这样dePHP文件,其HTML样式在DreamWeaver中可以正确de显示出来,所有dePHP相关代码会被看做HTML注释,而且在输出de时候,不会输出出来.比如,上面de文件在DreamWeaver中,被显示成:
PHP相关代码
[复制此相关代码]CODE:
Hello,$name!

这样,在设计页面de时候,我就可以借助DWde可视化界面,进行一些界面de修改,美化等工作.尽管没有实现完全de相关代码和HTMLde分离,但至少提供了一种辅助性de设计手段.

XStream使用方法总结附实例代码

星期一, 06月 2nd, 2008

XStream中de核心类就是XStream类,一般来说,熟悉这个类基本就够用了,如果您用de更多,估计是您设计有问题,否则不需要.
XStream对象相当Java对象和XML之间de转换器,转换过程是双向de.创建XSteam对象de方式很简单,只需要new XStream()即可.
Java到xml,用toXML()方法.
Xml到Java,用fromXML()方法.
在没有任何设置默认情况下,java到xmlde映射,是java成员名对应xmlde元素名,java类de全名对应xml根元素de名字.而实际中,往往是xml和java类都有了,要完成相互转换,必须进行别名映射.
别名配置包含三种情况:
1、类别名,用alias(String name, Class type).
2、类成员别名,用aliasField(String alias, Class definedIn, String fieldName)
3、类成员作为属性别名,用 aliasAttribute(Class definedIn, String attributeName, String alias),单独命名没有意义,还要通过useAttributeFor(Class definedIn, String fieldName) 应用到某个类上.
别名de配置是非常重要de,但是其中有些细节问题很重要,在例子中会专门做详细说明.
另外还有不太常用de方法:
addImplicitCollection(Class ownerType, String fieldName),去掉集合类型生成xmlde父节点.
registerConverter(Converter converter) ,注册一个转换器.
如果您dexml很大,或者为了安全性,以流de方式传输,那么XStream也提供丰富deAPI,
使用起来也非常简便.目前还用不到,暂不考虑.
如果这些基本de操作还不能满足您应用de需求,XStream提供丰富de扩展点.您可以实现自己de转换器.还可以利用XStream完成更负责de功能,比如输出其他非xml格式de数据,还可以输出html,还支持XML Dom类型数据,这些应用起来稍微复杂些.当然这些不是XStream应用de重点,也不用理会,真正需要de时候再查看API和源码研究研究.
XStreamde优点很多,但是也有一些小bug,比如在定义别名中de下划线“_”转换为xml后会变成“__”这个符号,很变态.因此,尽量避免在别名中实用任何符号,却是需要下划线de时候,可以考虑实用连接符“-”,这个没有问题.
另外,我deJava Bean中,常常有一些常量,在转换过程,XStream也会将这些常量转换过去,形成常量dexml节点,这显然不是想要de结果,对于常量字段,就不做转换了.

下面给出一个非常典型de而且实用de例子,作为对总结de补充:
package test;
import java.util.List;
/**
* Created by IntelliJ IDEA.<br>
* <b>User</b>: leizhimin<br>
* <b>Date</b>: 2008-5-22 21:10:13<br>
* <b>Note</b>: Please add comment here!
*/
public class Person {
private String name;
private String age;
private Profile profile;
private List<Address> addlist;
public Person(String name, String age, Profile profile, List<Address> addlist) {
this.name = name;
this.age = age;
this.profile = profile;
this.addlist = addlist;
}
public String toString() {
return “Person{”
“name=’” name ‘\”
“, age=’” age ‘\”
“, profile=” profile
“, addlist=” addlist
‘}’;
}
}
package test;
import java.sql.Date;
/**
* Created by IntelliJ IDEA.<br>
* <b>User</b>: leizhimin<br>
* <b>Date</b>: 2008-5-22 21:10:32<br>
* <b>Note</b>: Please add comment here!
*/
public class Profile {
private String job;
private String tel;
private String remark;
public Profile(String job, String tel, String remark) {
this.job = job;
this.tel = tel;
this.remark = remark;
}
public String toString() {
return “Profile{”
“job=’” job ‘\”
“, tel=’” tel ‘\”
“, remark=’” remark ‘\”
‘}’;
}
}
package test;
/**
* Created by IntelliJ IDEA.<br>
* <b>User</b>: leizhimin<br>
* <b>Date</b>: 2008-5-22 21:10:22<br>
* <b>Note</b>: Please add comment here!
*/
public class Address {
private String add;
private String zipcode;
public Address(String add, String zipcode) {
this.add = add;
this.zipcode = zipcode;
}

public String toString() {
return “Address{”
“add=’” add ‘\”
“, zipcode=’” zipcode ‘\”
‘}’;
}
}
package test;
import com.thoughtworks.xstream.XStream;
import java.util.List;
import java.util.ArrayList;
/**
* Created by IntelliJ IDEA.<br>
* <b>User</b>: leizhimin<br>
* <b>Date</b>: 2008-5-22 21:10:47<br>
* <b>Note</b>: XStream学习[http://lavasoft.blog.51cto.com]
*/
public class TestXStream {
public static void main(String args[]) {
test();
}
public static void test() {
System.out.println(”———-XStream学习:http://lavasoft.blog.51cto.com———-”);
//目标对象
Address address1 = new Address(”郑州市经三路”, “450001″);
Address address2 = new Address(”西安市雁塔路”, “710002″);
List<Address> addList = new ArrayList<Address>();
addList.add(address1);
addList.add(address2);
Profile profile = new Profile(”软件工程师”, “13512129933″, “备注说明”);
Person person = new Person(”熔岩”, “27″, profile, addList);
//转换装配
XStream xStream = new XStream();
/************** 设置类别名 ****************/
xStream.alias(”PERSON”, test.Person.class);
xStream.alias(”PROFILE”, test.Profile.class);
xStream.alias(”ADDRESS”, test.Address.class);
output(1, xStream, person);
/************* 设置类成员de别名 ***************/
//设置Person类dename成员别名Name
xStream.aliasField(”Name”, Person.class, “name”);
/*[注意] 设置Person类deprofile成员别名PROFILE,这个别名和Profile类de别名一致,
* 这样可以保持XStream对象可以从profile成员生成dexml片段直接转换为Profile成员,
* 如果成员profilede别名和Profilede别名不一致,则profile成员生成dexml片段不可
* 直接转换为Profile对象,需要重新创建XStream对象,这岂不给自己找麻烦? */
xStream.aliasField(”PROFILE”, test.Person.class, “profile”);
xStream.aliasField(”ADDLIST”, test.Person.class, “addlist”);
xStream.aliasField(”Add”, test.Address.class, “add”);
xStream.aliasField(”Job”, test.Profile.class, “job”);
output(2, xStream, person);
/******* 设置类成员为xml一个元素上de属性 *******/
xStream.useAttributeFor(Address.class, “zipcode”);
/************* 设置属性de别名 ***************/
xStream.aliasAttribute(test.Address.class, “zipcode”, “Zipcode”);
output(3, xStream, person);
/************* 将xml转为java对象 ******×****/
String person_xml = “<PERSON>\n”
” <Name>熔岩</Name>\n”
” <age>27</age>\n”
” <PROFILE>\n”
” <Job>软件工程师</Job>\n”
” <tel>13512129933</tel>\n”
” <remark>备注说明</remark>\n”
” </PROFILE>\n”
” <ADDLIST>\n”
” <ADDRESS Zipcode=\”450001\”>\n”
” <Add>郑州市经三路</Add>\n”
” </ADDRESS>\n”
” <ADDRESS Zipcode=\”710002\”>\n”
” <Add>西安市雁塔路</Add>\n”
” </ADDRESS>\n”
” </ADDLIST>\n”
“</PERSON>”;
String profile_xml = ” <PROFILE>\n”
” <Job>软件工程师</Job>\n”
” <tel>13512129933</tel>\n”
” <remark>备注说明</remark>\n”
” </PROFILE>”;
String address_xml = ” <ADDRESS Zipcode=\”710002\”>\n”
” <Add>西安市雁塔路</Add>\n”
” </ADDRESS>”;
//同样实用上面deXStream对象xStream
System.out.println(xStream.fromXML(person_xml).toString());
System.out.println(xStream.fromXML(profile_xml).toString());
System.out.println(xStream.fromXML(address_xml).toString());
}
public static void output(int i, XStream xStream, Object obj) {
String xml = xStream.toXML(obj);
System.out.println(”>>>第[ " i "]次输出\n”);
System.out.println(xml “\n”);
}
}
———-XStream学习:http://lavasoft.blog.51cto.com———-
>>>第[ 1]次输出
<PERSON>
<name>熔岩</name>
<age>27</age>
<profile>
<job>软件工程师</job>
<tel>13512129933</tel>
<remark>备注说明</remark>
</profile>
<addlist>
<ADDRESS>
<add>郑州市经三路</add>
<zipcode>450001</zipcode>
</ADDRESS>
<ADDRESS>
<add>西安市雁塔路</add>
<zipcode>710002</zipcode>
</ADDRESS>
</addlist>
</PERSON>
>>>第[ 2]次输出
<PERSON>
<Name>熔岩</Name>
<age>27</age>
<PROFILE>
<Job>软件工程师</Job>
<tel>13512129933</tel>
<remark>备注说明</remark>
</PROFILE>
<ADDLIST>
<ADDRESS>
<Add>郑州市经三路</Add>
<zipcode>450001</zipcode>
</ADDRESS>
<ADDRESS>
<Add>西安市雁塔路</Add>
<zipcode>710002</zipcode>
</ADDRESS>
</ADDLIST>
</PERSON>
>>>第[ 3]次输出
<PERSON>
<Name>熔岩</Name>
<age>27</age>
<PROFILE>
<Job>软件工程师</Job>
<tel>13512129933</tel>
<remark>备注说明</remark>
</PROFILE>
<ADDLIST>
<ADDRESS Zipcode=”450001″>
<Add>郑州市经三路</Add>
</ADDRESS>
<ADDRESS Zipcode=”710002″>
<Add>西安市雁塔路</Add>
</ADDRESS>
</ADDLIST>
</PERSON>
Person{name=’熔岩’, age=’27′, profile=Profile{job=’软件工程师’, tel=’13512129933′, remark=’备注说明’}, addlist=[Address{add='郑州市经三路', zipcode='450001'}, Address{add='西安市雁塔路', zipcode='710002'}]}
Profile{job=’软件工程师’, tel=’13512129933′, remark=’备注说明’}
Address{add=’西安市雁塔路’, zipcode=’710002′}
Process finished with exit code 0
在实际中,类de属性很多,嵌套层次也很复杂,如果仅仅使用XStream原生API来硬编码设置别名等属性,显得太生硬也难以维护.完全可以考虑通过一个xml配置文件来定义所有用到de类de别名定义(包括其成员),然后,通过读取配置构建一个XStreamde工厂,在用到时候直接去取,而不是让实用者组装.我目前de一个项目中,就是这么实现de,效果非常de好.
下面我给出针对上面提出de问题一个解决方案:
思想:考虑做一个过滤器,在xml转java之前,在Java转xml之后,应用这个过滤器.这个过滤器提供将xml中de“__”替换为“-”,并且将xml中de不需要de节点剔除.
在过滤之前,我实现了个转换器装配,这一步通过xml来配置,并在java中获取.
相关代码就省略了,这一步很灵活,关键看您de应用了.
为了能过滤xml,我需要用Dom4j递归遍历xml文档.下面一些算法相关代码:
//递归算法:遍历配置文件,找出所有有效dexpath
private static void recursiveElement(Element element) {
List<Element> elements = element.elements();
validXPathList.add(element.getPath());
if (elements.size() == 0) {
//没有子元素
} else {
//有子元素
for (Iterator<Element> it = elements.iterator(); it.hasNext();) {
//递归遍历
recursiveElement(it.next());
}
}
}
//递归算法:遍历xml,标识无效de元素节点
private static void recursiveFixElement(Element element) {
List<Element> elements = element.elements();
if (!validXPathList.contains(element.getPath())) {
element.addAttribute(”delete”, “true”);
}
if (elements.size() == 0) {
//没有子元素
} else {
//有子元素
for (Iterator<Element> it = elements.iterator(); it.hasNext();) {
Element e = it.next();
if (!validXPathList.contains(e.getPath())) {
e.addAttribute(”delete”, “true”);
}
//递归遍历
recursiveFixElement(e);
}
}
}
/**
* 过滤器接口方法,转换不规范字符,剔除无效节点
*
* @param xmlStr 要过滤dexml
* @return 符合转换器要求dexml
*/
public static String filter(String xmlStr) {
Document document = null;
try {
document = DocumentHelper.parseText(xmlStr.replaceAll(”__”, “_”));
//递归de调用:标记要剔除dexml元素
recursiveFixElement(document.getRootElement());
List<Node> nodeList = document.selectNodes(”//@delete”);
for (Node node : nodeList) {
node.getParent().detach(); //剔除xml元素
}
} catch (DocumentException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
return document.asXML();
}

Jsp页面实现文件上传下载类代码第1/2页

星期一, 06月 2nd, 2008

刚才和lp看完电影,把jsp页面抽出class调整了一下.最近总上经典,是感觉既然当了斑竹,就该留下点什么.lp这几天也半开玩笑半生气de说,一回来就上经典,就发帖,您干脆娶经典作lp得了.想想,这几天是有点夸张,以后放慢速度了.保持1星期1帖吧,那样也能多想写,多总结些.
发帖de初衷就是有时候看到有de朋友问de问题,似乎还没有走进javade门,希望这样de帖子,能对新手一点帮助,也就满足了.有时候随意de一段话,其实也是自己de一点经验,而有时候之所以絮絮叨叨,是想把问题说de清楚明白,让高手见笑了.因为在入门de时候,每一个小环节都可能郁闷半天,如果看到我de某段话,有所帮助de话,即使我说十句有一句有帮助,我也满足了.因为我在不停de说话.

现在把总结dejsp页面上传类发布出来.相关代码肯定还会存在问题,有bugde话,告诉我,我及时修正.

名称:jsp页面上传类
作者:SinNeR
Mail:vogoals[at]hotmail.com

特点:

  1. 可以多文件上传;

  2. 返回上传后de文件名;

  3. form表单中de其他参数也可以得到.

先贴上传类,JspFileUpload

package com.vogoal.util;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
/*
* vogoalAPI 1.0
* Auther SinNeR@blueidea.com
* by vogoal.com
* mail: vogoals@hotmail.com
*/
/**
* JSP上传文件类
*
* @author SinNeR
* @version 1.0
*/
public class JspFileUpload {
/** request对象 */
private HttpServletRequest request = null;
/** 上传文件de路径 */
private String uploadPath = null;
/** 每次读取得字节de大小 */
private static int BUFSIZE = 1024 * 8;
/** 存储参数deHashtable */
private Hashtable paramHt = new Hasptable();
/** 存储上传de文件de文件名deArrayList */
private ArrayList updFileArr = new ArrayList();
/**
* 设定request对象.
*
* @param request
* HttpServletRequest request对象
*/
public void setRequest(HttpServletRequest request) {
this.request = request;
}
/**
* 设定文件上传路径.
*
* @param path
* 用户指定de文件de上传路径.
*/
public void setUploadPath(String path) {
this.uploadPath = path;
}
/**
* 文件上传处理主程序.�������B
*
* @return int 操作结果 0 文件操作成功;1 request对象不存在. 2 没有设定文件保存路径或者文件保存路径不正确;3
* 没有设定正确deenctype;4 文件操作异常.
*/
public int process() {
int status = 0;
// 文件上传前,对request对象,上传路径以及enctype进行check.
status = preCheck();
// 出错de时候返回错误相关代码.
if (status != 0)
return status;
try {
// ��参数或者文件名�u��
String name = null;
// 参数devalue
String value = null;
// 读取de流是否为文件de标志位
boolean fileFlag = false;
// 要存储de文件.
File tmpFile = null;
// 上传de文件de名字
String fName = null;
FileOutputStream baos = null;
BufferedOutputStream bos = null;
// ��存储参数deHashtable
paramHt = new Hashtable();
updFileArr = new ArrayList();
int rtnPos = 0;
byte[] buffs = new byte[BUFSIZE * 8];
// �取得ContentType
String contentType = request.getContentType();
int index = contentType.indexOf(”boundary=”);
String boundary = “–” contentType.substring(index 9);
String endBoundary = boundary “–”;
// �从request对象中取得流.
ServletInputStream sis = request.getInputStream();
// 读取1行
while ((rtnPos = sis.readLine(buffs, 0, buffs.length)) != -1) {
String strBuff = new String(buffs, 0, rtnPos);
// 读取1行数据�n��
if (strBuff.startsWith(boundary)) {
if (name != null && name.trim().length() > 0) {
if (fileFlag) {
bos.flush();
baos.close();
bos.close();
baos = null;
bos = null;
updFileArr.add(fName);
} else {
Object obj = paramHt.get(name);
ArrayList al = new ArrayList();
if (obj != null) {
al = (ArrayList) obj;
}
al.add(value);
System.out.println(value);
paramHt.put(name, al);
}
}
name = new String();
value = new String();
fileFlag = false;
fName = new String();
rtnPos = sis.readLine(buffs, 0, buffs.length);
if (rtnPos != -1) {
strBuff = new String(buffs, 0, rtnPos);
if (strBuff.toLowerCase().startsWith(
“content-disposition: form-data; “)) {
int nIndex = strBuff.toLowerCase().indexOf(
“name=\”");
int nLastIndex = strBuff.toLowerCase().indexOf(
“\”", nIndex 6);
name = strBuff.substring(nIndex 6, nLastIndex);
}
int fIndex = strBuff.toLowerCase().indexOf(
“filename=\”");
if (fIndex != -1) {
fileFlag = true;
int fLastIndex = strBuff.toLowerCase().indexOf(
“\”", fIndex 10);
fName = strBuff.substring(fIndex 10, fLastIndex);
fName = getFileName(fName);
if (fName == null || fName.trim().length() == 0) {
fileFlag = false;
sis.readLine(buffs, 0, buffs.length);
sis.readLine(buffs, 0, buffs.length);
sis.readLine(buffs, 0, buffs.length);
continue;
}else{
fName = getFileNameByTime(fName);
sis.readLine(buffs, 0, buffs.length);
sis.readLine(buffs, 0, buffs.length);
}
}
}
} else if (strBuff.startsWith(endBoundary)) {
if (name != null && name.trim().length() > 0) {
if (fileFlag) {
bos.flush();
baos.close();
bos.close();
baos = null;
bos = null;
updFileArr.add(fName);
} else {
Object obj = paramHt.get(name);
ArrayList al = new ArrayList();
if (obj != null) {
al = (ArrayList) obj;
}
al.add(value);
paramHt.put(name, al);
}
}
} else {
if (fileFlag) {
if (baos == null && bos == null) {
tmpFile = new File(uploadPath fName);
baos = new FileOutputStream(tmpFile);
bos = new BufferedOutputStream(baos);
}
bos.write(buffs, 0, rtnPos);
baos.flush();
} else {
System.out.println(”test :” value “–” strBuff);
value = value strBuff;
}
}
}
} catch (IOException e) {
status = 4;
}
return status;
}
private int preCheck() {
int errCode = 0;
if ( request == null )
return 1;
if ( uploadPath == null || uploadPath.trim().length() == 0 )
return 2;
else{
File tmpF = new File(uploadPath);
if (!tmpF.exists())
return 2;
}
String contentType = request.getContentType();
if ( contentType.indexOf(”multipart/form-data”) == -1 )
return 3;
return errCode;
}
public String getParameter(String name){
String value = “”;
if ( name == null || name.trim().length() == 0 )
return value;
value = (paramHt.get(name) == null)?”":(String)((ArrayList)paramHt.get(name)).get(0);
return value;
}
public String[] getParameters(String name){
if ( name == null || name.trim().length() == 0 )
return null;
if ( paramHt.get(name) == null )
return null;
ArrayList al = (ArrayList)paramHt.get(name);
String[] strArr = new String[al.size()];
for ( int i=0;i<al.size();i )
strArr[i] = (String)al.get(i);
return strArr;
}
public int getUpdFileSize(){
return updFileArr.size();
}
public String[] getUpdFileNames(){
String[] strArr = new String[updFileArr.size()];
for ( int i=0;i<updFileArr.size();i )
strArr[i] = (String)updFileArr.get(i);
return strArr;
}
private String getFileName(String input){
int fIndex = input.lastIndexOf(”\\”);
if (fIndex == -1) {
fIndex = input.lastIndexOf(”/”);
if (fIndex == -1) {
return input;
}
}
input = input.substring(fIndex 1);
return input;
}
private String getFileNameByTime(String input){
int index = input.indexOf(”.”);
Date dt = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(”yyyyMMddHHmmssSSS”);
return input.substring(0,index) sdf.format(dt) input.substring(index);
}
}

说明:

这个类基本解决了上一贴de上一贴说de存在debug和不足.主要做了如下修正.

  1. 用户可以设定文件上传de路径,这里没有用request对象degetRealPath方法来取得相对路径,而是用了绝对路径.是一个小败笔.因为有时候用户只是得到服务器de一个应用,而不知道整个服务器de路径.但是既然getRealPath自己可以得到,用户自己取得也可以.

  2. 在文件上传处理de时候,预先进行了check,把一些可能出现de造成上传失败de情况拍查掉.避免该类出现不该出现de异常.

  3. 捕获了IO异常,避免文件上传de时候出现异常时程序de不友好表现

  4. 提供了方法返回form表单中其他参数de取得,模拟了HttpServletRequest对象degetParameter和getParameters方法(后面这个方法是叫这个名字么-_-b),取得Parameterde名称de方法没有提供,是个小缺陷.

  5. 提供了方法返回上传de文件de件数和上传de文件名,方便用户作其他操作.

现在介绍下JSP页面中如何用这个类实现上传.

首先,要把这个类编译后declass文件拷贝到WEB-INF/classes/目录下.注意保持packagede结构.

在jsp页面中引用这个类

<%@page import=”com.vogoal.util.JspFileUpload”%>

<%
//初始化
JspFileUpload jfu = new JspFileUpload();
//设定request对象
jfu.setRequest(request);
//设定上传de文件路径
jfu.setUploadPath(”C:\\”);
//上传处理
int rtn = jfu.process();
//取得form中其他input控件参数de值
String username = jfu.getParameter(”username”);
//如果对应同一个参数有多个input控件,返回数组
String[] usernameArr = jfu.getParameters(”username”);
//取得上传de文件de名字
String[] fileArr = jfu.getUpdFileNames();
//取得上传文件de个数,这个方法有点鸡肋
int fileNumber = jfu.getUpdFileSize();
//下面de是测试输出de相关代码.
// out.println(”parameter:” username);
// out.println(”parameter size:” usernameArr.length);
// out.println(”fileArr size:” fileArr.length);
// if (fileArr.length > 0)
// out.println(”fileArr 0:” fileArr[0]);
%>

使用de时候de注意事项:

  1. 一定要设定request对象.

  2. 一定要设定正确de上传路径.

  3. 执行完了之后才可以得到其他参数,因为执行了之后这些参数才被分析.

1,2两点如果没有做到de话,process方法执行de时候汇报错.

各个用户可用de方法及说明:

设定requet对象.
public void setRequest(HttpServletRequest request)
设定文件上传de路径.
public void setUploadPath(String path)
文件上传处理主程序.
@return int 操作结果 0 文件操作成功;1 request对象不存在. 2 没有设定文件保存路径或者文件保存路径不正确;3
没有设定正确deenctype;4 文件操作异常.
public int process()

根据name取得form表单中其他传递de参数de值(多个de话返回其中一个)
public String getParameter(String name)

根据name取得form表单中其他传递de参数de值(返回数组,可有多个)
public String[] getParameters(String name)

取得上传成功文件de个数
public int getUpdFileSize()

取得上传de文件名对应de数组.
public String[] getUpdFileNames()

注意process方法地返回值,在不是0de情况下操作失败.

以下提供测试类以及测试页面(见附件):

HelloPostFile.html
HelloPostFile.jsp
写在jsp中de相关代码de测试文件.
HelloPostFileWithClass.html
HelloPostFileWithClass.jsp
抽出class后de测试文件.
src在
WEB-INF/src/
class在
WEB-INF/classes/

另:
由于这个文件被我在中文日文系统下编辑过,注释出现乱码,所以大部分都删掉了,见谅.

下载:WEB-INF.zip

jsp中文乱码 jsp mysql 乱码的解决方法

星期一, 06月 2nd, 2008

jsp中文乱码 jsp mysql 乱码要servlet里面支持中文de方法:
在dopost或者dogetde第一句加上:
request.setCharacterEncoding(”GB2312″);
response.setCharacterEncoding(”GB2312″);
jsp乱码问题在jsp里面就把
<%@ page contentType=”text/html; charset=gb2312″ language=”java” import=”java.sql.*” errorPage=”" %>
里设置成charset=gb2312
jsp页面乱码 jsp页面中文乱码 如果这样还不行,就只有在取出中文后(getParameter)强制转换了:
String str=new String(request.getParameter(”text”).getBytes(”ISO-8859-1″),”GB2312″);
很不错de方法,因为在java里面,jsp数据库乱码是个大问题,jsp出现乱码这些一定要铭记

weblogic 8.1下重新编译java类但不用重启服务器的方法

星期一, 06月 2nd, 2008

重新编译jsp是不用重启服务期de,但类就需要.
所以需要设置一下::
在weblogic.xml文件里加上下面de一句即可(红色标示)
<weblogic-web-app>
<container-descriptor>
<servlet-reload-check-secs>-1</servlet-reload-check-secs>
</container-descriptor>
<context-root>ccbroot</context-root>
</weblogic-web-app>

但缺点是每次都重新加载所有deservlet和jsp页面,比较耗资源!!呵呵

JSP下动态INCLUDE与静态INCLUDE的区别分析

星期一, 06月 2nd, 2008

动态INCLUDE
用jsp:include动作实现 <jsp:include page=”included.jsp” flush=”true” />它总是会检查所含文件中de变化,适合用于包含动态页面,并且可以带参数.
静态INCLUDE
用include伪码实现,定不会检查所含文件de变化,适用于包含静态页面<%@ include file=”included.htm” %>
===================================================================
1. 静态includede结果是把其他jsp引入当前jsp,两者合为一体
动态includede结构是两者独立,直到输出时才合并( 看看jsp生成dejava文件就可以知道了)
2.正是因为这样,动态includedejsp文件独立性很强,是一个单独dejsp文件,需要使用de对象,页面设置,都必须有自己创建,当然,还好它和include它de页面derequest范围是一致de.
而静态include纯粹是把相关代码写在外面de一种共享方法,所有de变量都是可以和include它de主文件共享,两者高度紧密结合,不能有变量同名de冲突.而页面设置也可以借用主文件de.

RMI使用学习 小结

星期一, 06月 2nd, 2008

四年前也是 Java de fans,也曾如火如荼de追求着 sun,追求着 java. 当然 RMI 肯定不会放过,但到目前为止还没有在任何一个项目中用过,昨天听了一个 java 老师de课,本来不去想听,可想想我交了这么多 money,最后还是去.最叫人恶心de是他讲de RMI 一点实用价值都没有,而且有de理论也不对.真de误导人啊,学术理论和实践是不能够分离de,老师是这样de,只能靠学生自己动手丰衣足食了.昨天晚上用了一点时间,从新研究了一下 RMI.举个例子作为 RMI 学习de终结吧.
在写这篇文章前也访问了中国电信de高级工程师,根据他de介绍,RMI 有很多实现方式,而且现在他发现 RMI 在大规模分布式系统中,效率和性能不是很好.目前他带领de团队正在自行开发分布式应用.
随着 web 2.0 时代de到来,SOA 开发思想de普及应用.分布式应用,将又一次走向高潮.
RMI 开发步骤大家都很清楚,这里举个不用手动启动 rmiRegistry, 也不要指定 codebase 和web server de例子.底层 TCP/IP 细节我不用去管他,您就把他看成像 SOAP、JNDI 等一样de基于注册服务de东西就行了 .
1. 远程接口
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IRMI extends Remote {
public Object invoke(ITask task) throws RemoteException;
}
2.远程接口实现
/**
* @author Jack.Wang
*
*/
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class IRMIImpl extends UnicastRemoteObject implements IRMI {
protected IRMIImpl() throws RemoteException {
super();
}
public Object invoke(ITask task) throws RemoteException {
System.out.println(”注意:这是一个远程调用”);
Object obj = task.doWork();
System.out.println(”调用ITask.doWork()方法de返回值:” obj.toString());
// 客户端调用,可以在服务器端播放需要de音乐
ProcessCaller.callMp3();
return obj;
}
}
3. 任务接口
/**
* @author Jack.Wang
*
*/
import java.io.Serializable;
public interface ITask extends Serializable {
public Object doWork();
}
4. 任务实现类
/**
* @author Jack.Wang
*
*/
public class TaskImpl implements ITask {
public Object doWork() {
System.out.println(”当前程序处于远程调用中”);
return Thread.currentThread().getName() ” ”
new Date(System.currentTimeMillis());
}
}
5.在java中调用windows程序
public class ProcessCaller {
public static void callMp3() {
Runtime ru = Runtime.getRuntime();
try {
// 调用播放器文件播放指定MP3
Process p1 = ru
.exec(”C:\\Program Files\\Windows Media Player\\wmplayer D:\\Jack\\Mp3\\5.秋天不回来-王强.mp3″);
} catch (Exception e) {
}
}
}
6. Server 端相关代码
/**
* @author Jack.Wang
*
*/
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void registRemoteObject() throws Exception {
IRMIImpl impl = new IRMIImpl();
Naming.rebind(”rmi://210.43.109.25:1111/mytask”, impl);
System.out.println(”bound success!”);
}
private static Registry createRegistry() {
Registry registry = null;
int port = 1111;
try {
registry = LocateRegistry.getRegistry(”210.43.109.25″, port);
registry.list();
System.out.println(”Register the exist server!”);
} catch (final Exception e) {
try {
registry = LocateRegistry.createRegistry(port);
System.out.println(”Register the exist server!port=” port);
} catch (final Exception ee) {
ee.printStackTrace();
}
}
return registry;
}
/**
* 将对象注册到rmi服务器上
*/
public static void bind() {
Registry registry = null;
registry = createRegistry();
try {
IRMIImpl impl = new IRMIImpl();
registry.rebind(”mytask”, impl);
System.out.println(”mytask server start!”);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
try {
bind();
} catch (Exception e) {
e.printStackTrace();
}
}
}
7. Client 端相关代码
/**
* @author Jack.Wang
*
*/
public class RMIClient {
public static void getRemoteObject() throws Exception {
IRMI obj = (IRMI) Naming.lookup(”rmi://210.43.109.28:1111/mytask”); // 得到远程发布de服务
TaskImpl task = new TaskImpl();
Object result = obj.invoke(task); // 调用远程服务de方法
System.out.println(result.toString());
}
public static void main(String[] args) {
try {
getRemoteObject();
} catch (Exception e) {
e.printStackTrace();
}
}
}
小结:
建议把以上程序打包成 jar 文件,您可以在不同机子间测试.
RMI 就这么简单,如果您觉得他不爽,就自己封装 socket. 到时候要通知我哦,我也学习学习.

搭建SSH时的思考和遇到的几个问题的解决方法

星期一, 06月 2nd, 2008

SSH流行很久了,一直看到官方文档和网上都在讲如何整合SSH,讨论各种整合de优缺点.今天我比较闲,也用我de一些想法来试着整合这三个最流行de框架.
本次所用版本为:Struts 1.3.9 Spring 2.5 Hiberante 3.2
开发工具和环境为:Eclipse 3.3 MyEclipse 6.0 JBoss 4.2 Tomcat
用SSH时,我de架构自然就会分成三层,即表现层,逻辑层和持久层,按照Martin Flowerde指导思想,耦合越少越好,下层为上层提供服务,这也是Rod开发Springde指导思想之一,所以我首先想到de就是如何减少到最低de耦合.
根据Spring 2.0官方文档中推荐de做法,Spring与Struts1.x集成,有采用代理类de方式,也有用ActionSupportde方式,但是我认为这两种方式无疑都有很强de侵入性和依赖性,这与Springde思想有些矛盾.
我采用AutowiringRequestProcessor来做,这个类会自动为您装载您所需要deService,根据其Java Docde提示,其默认是byType匹配de,当然您也可以用byNamede方式,我认为以Typede方式就OK了.来看看两个配置文件吧,先来看看Strutsde配置文件struts-config.xml:
1 <? xml version=”1.0″ encoding=”UTF-8″ ?>
2 <! DOCTYPE struts-config PUBLIC “-//Apache Software Foundation//DTD Struts Configuration 1.3//EN” “http://struts.apache.org/dtds/struts-config_1_3.dtd” >
3
4 < struts-config >
5 < form-beans >
6 < form-bean name =”loginForm” type =”com.***.ssh.view.login.LoginForm” />
7 </ form-beans >
8
9 < global-exceptions />
10 < global-forwards />
11 < action-mappings >
12 < action name =”loginForm” path =”/login” scope =”request”
13 type =”com.***.ssh.view.login.LoginAction” validate =”false” />
14 </ action-mappings >
15
16 < controller
17 processorClass =”org.springframework.web.struts.AutowiringRequestProcessor” />
18
19 < message-resources parameter =”ApplicationResources” />
20 </ struts-config >
21
22
这个文件中可以发现,跟没有与Spring集成时就一点不一样,多了一行:
<controller processorClass=”org.springframework.web.struts.AutowiringRequestProcessor” />
再来看看Springde配置文件applicationContext.xml:
1 <? xml version=”1.0″ encoding=”UTF-8″ ?>
2 <! DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd” >
3
4 < beans >
5
6 < bean id =”SSHSessionFactory”
7 class =”org.springframework.orm.hibernate3.LocalSessionFactoryBean” >
8 < property name =”configLocation” >
9 < value > classpath:hibernate.cfg.xml </ value >
10 </ property >
11 </ bean >
12
13 < bean name =”LoginService”
14 class =”com.***.ssh.biz.login.LoginService” singleton =”false” >
15 < property name =”dao” >
16 < ref bean =”UsersDao” />
17 </ property >
18 </ bean >
19
20 < bean id =”UsersDao” class =”com.***.ssh.persistence.UserDao” >
21 < property name =”sessionFactory” >
22 < ref bean =”SSHSessionFactory” />
23 </ property >
24 </ bean >
25 </ beans >
26
这里面也没有多余de内容,不会出现代理方式时,多份XML同时配置de问题,减少了维护量.
同时,您会发现,我并没有把Hibernatede具体配置放在这里面,而是用Hibernate自身de配置来管理.
这样de话,我三层之间de依赖性会降到较低,两头可以任意换到其中de某一层.
顺便要说de是,常见de书籍上面发现往往不会有如此深入de探讨,难道是怕初学者看不懂吗?
另外,对于一个架构来说,要解决de问题决不是指这些,通常我可以采用RUPde4+1视图de方法去考虑架构de方方面面.我也可以从以下一些方面来各个击破:安全性,数据输入输出de校验与转换,国际化,LOG,异常处理,异构系统整合,后台运行程序等等.如果是多个数据库,我还需要更多de考虑事务控制.
我想我后面会去完善这个整合,并实现一个Demo,作为小de简单de项目快速开发de基础.

整合时遇到过如下问题:
问题1:启动时出现 “严重: Error listenerStart ”
这个问题,网上有很多解决办法:
有一种最简单de解决办法是把用Listener初始化Spring改为用Servlet初始化Spring,但这样de方法不太好,一是没有找到根源,二是可能会带来新de问题.
比较好de一种解决办法是,加上Log4Jde相关配置,然后再启动时,就会出现各类详细信息,这样可根据具体信息再来解决,一般可能是DataSource配置,或环境配置有问题.
参考网址:http://hi.baidu.com/xht314/blog/item/808ecf13c1dd1820dd5401af.html
问题2:遇到“Required extension qdox not found”这样de提示
网上也有解答,我用de方法是直接把commons-attributes-compiler.jar这个包去掉.当然如果您要用到这个包de话,可以参考下面这个地址:
http://hi.baidu.com/sky_lei/blog/item/77ee17085543b232e8248824.html
问题3:Struts包与Spring包冲突de问题
我遇到包有冲突,换成Struts需要de优先就OK了,现在deJAR档越来越麻烦了,很多项目deJAR档都被开发人员搞得乱七八糟,看来Maven是个好东西,至少思想是好de,可能下一步需要研究一下.

经常听朋友说什么J2EE,终于知道点什么是J2EE了,汗一个

星期一, 06月 2nd, 2008

经常听朋友说什么J2EE,终于知道点什么是J2EE了,汗一个,上网搜了下这个说de比较详细了,J2EE,Java2平台企业版(Java 2 Platform Enterprise Edition), 是Sun公司为企业级应用推出de标准平台.Java平台共分为三个主要版本Java EE、Java SE和Java ME.
Sun公司在1998年发表JDK1.2版本de时候,使用了新名称Java 2 Platform,即“Java2平台”,修改后deJDK称为Java 2 Platform Software Develping Kit,即J2SDK.并分为标准版(Standard Edition,J2SE), 企业版(Enterprise Edition,J2EE),微型版(MicroEdition,J2ME).J2EE便由此诞生.
2005年6月,JavaOne大会召开,SUN公司公开Java SE 6.此时,Javade各种版本已经更名以取消其中de数字“2”:J2EE更名为Java EE, J2SE更名为Java SE,J2ME更名为Java ME.
随着Java技术de发展,J2EE平台得到了迅速de发展,成为Java语言中最活跃de体系之一.现如今,J2EE不仅仅是指一种标准平台(Platform),她更多de表达着一种软件架构和设计思想.
J2EE是一系列技术标准所组成de平台,包括:
* Applet - Java Applet
* EJB - 企业级JavaBean(Enterprise Java Beans)
* JAAS - Java Authentication and Authorization Service
* JACC - J2EE Authorization Contract for Containers
* JAF - Java Beans Activation Framework
* JAX-RPC - Java API for XML-Based Remote Procedure Calls
* JAX-WS - Java API for XML Web Services
* JAXM
* JAXP - Java XML解析API(Java API for XML Processing)
* JAXR - Java API for XML Registries
* JCA - J2EE连接器架构(J2EE Connector Architecture)
* JDBC - Java数据库联接(Java Database Connectivity)
* JMS - Java消息服务(Java Message Service)
* JMX - Java Management
* JNDI - Java名字与目录接口(Java Naming and Directory Interface)
* JSF - Java Server Faces
* JSP - Java服务器页面(Java Server Pages)
* JSTL - Java服务器页面标准标签库(Java Server Pages Standard Tag Library)
* JTA - Java事务API(Java Transaction API)
* JavaMail
* Servlet - Java Servlet API
* StAX - Streaming APIs for XML Parsers
* WS - Web Services

一个jsp AJAX评论系统第1/2页

星期一, 06月 2nd, 2008

这是一个简单de评论系统,使用了JDOM(这边使用Jdom-b9),实例使用JSP作为视图,结合使用AJAX(用到prototype-1.4),Servlet和JavaBean作为后台处理,使用xml文件存储数据.
1.应用目录结构如下:
data
|–comment.xml
js
|–prototype.js
|–ufo.js(UTF-8格式)
css
|–ufo.css
images
|–loading.gif
ufo.jsp(UTF-8格式)
WEB-INF
|-lib
|-jdom.jar
|-classes

|-web.xml
/*********************************************
*Author:Java619
*Time:2007-02-14
**********************************************/

2.后台JavaBean CommentBean.java
/** *//**
* <P>外星人是否存在评论系统</p>
* @author ceun
* 联系作者:<br>
* <a href=”mailto:ceun@163.com”>ceun</a><br>
* @version 1.0 2007-01-30 实现基本功能<br>
* CommentBean.java
* Created on Jan 30, 2007 9:39:19 AM
*/
package com.ceun.bean;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import org.jdom.CDATA;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Text;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
/** *//**
*<p> 封装对XMLde操作</p>
* @author ceun
* 联系作者:<br>
* <a href=”mailto:ceun@163.com”>ceun</a><br>
* @version 1.0 2007-01-30 实现基本功能<br>
*/
public class CommentBean …{
private String filepath;
private SAXBuilder builder = null;
private Document doc = null;
public CommentBean() …{
}
/** *//**
* 初始化XML文件路径,加载文件
* */
public CommentBean(String path) …{
this.filepath = path;
builder = new SAXBuilder();
try …{
doc = builder.build(filepath);
} catch (JDOMException e) …{
System.out.print(”找不到指定deXML文件”);
e.printStackTrace();
} catch (IOException e) …{
System.out.print(”找不到指定de文件”);
e.printStackTrace();
}
}
/** *//**
* 添加评论
* @param nikename 评论者昵称
* @param comment 评论内容
* @param attitude 评论者de结论(yes-存在,no-不存在)
* */
public String addComment(String nikename, String comment, String attitude) …{
Element root = doc.getRootElement();
Element el = new Element(”comment”);
Random rand = new Random();
int id = rand.nextInt(10000);
el.setAttribute(”id”, “comment_” id);
el.setAttribute(”attitude”, attitude);
Element name = new Element(”nikename”);
CDATA cname = new CDATA(nikename);
name.addContent(cname);
Element data = new Element(”data”);
CDATA ctext = new CDATA(comment);
data.addContent(ctext);
SimpleDateFormat format = new SimpleDateFormat(”yyyy-MM-dd HH:mm:ss”);
Date date = new Date();
Text tdate = new Text(format.format(date));
Element pubdate = new Element(”pubdate”);
pubdate.addContent(tdate);
el.addContent(name);
el.addContent(data);
el.addContent(pubdate);
root.addContent(el);
XMLOutputter outputter = new XMLOutputter(” “, true, “GB2312″);
// 清除comment元素间de空格
outputter.setTrimAllWhite(true);
try …{
outputter.output(doc, new FileWriter(filepath));
} catch (IOException e) …{
System.out.println(”指定路径有错”);
e.printStackTrace();
}
return tdate.getText();
}
/** *//**
* 删除指定IDde评论
* @param commentId 评论ID
* @return 返回操作结果字符串(成功或失败)
* */
public String removeComment(String commentId) …{
Element root = doc.getRootElement();
List comments = root.getChildren();
int size = comments.size();
Element dist = null;
for (int i = 0; i < size; i ) …{
Element comment = (Element) comments.get(i);
String id = comment.getAttributeValue(”id”);
if (id.equals(commentId)) …{
dist = comment;
break;
}
}
if (dist != null) …{
root.removeContent(dist);
XMLOutputter outputter = new XMLOutputter(” “, true, “GB2312″);
// 清除comment元素间de空格
outputter.setTrimAllWhite(true);
try …{
outputter.output(doc, new FileWriter(filepath));
} catch (IOException e) …{
System.out.println(”重写文件有出错”);
e.printStackTrace();
}
return “成功删除指定元素!”;
} else
return “指定元素不存在!”;
}
/** *//**
* 批量删除评论
* @param commentIdArgs 评论ID数组
* @return 返回操作结果字符串(成功或失败)
* */
public String removeComments(String[] commentIdArgs) …{
Element root = doc.getRootElement();
List comments = root.getChildren();
int size = comments.size();
int len = commentIdArgs.length;
List<Element> dist = new ArrayList<Element>();
outer:for (int i = 0; i < size; i ) …{
Element comment = (Element) comments.get(i);
String id = comment.getAttributeValue(”id”);
for (int j = 0; j < len; j )
if (id.equals(commentIdArgs[j])) …{
dist.add(comment);
continue outer;
}
}
int dist_size=dist.size();
if (dist_size != 0) …{
for (int i = 0; i < dist_size; i )
root.removeContent(dist.get(i));
XMLOutputter outputter = new XMLOutputter(” “, true, “GB2312″);
// 清除comment元素间de空格
outputter.setTrimAllWhite(true);
try …{
outputter.output(doc, new FileWriter(filepath));
} catch (IOException e) …{
System.out.println(”重写文件有出错”);
e.printStackTrace();
}
return “成功删除指定de元素集合!”;
} else
return “指定元素集合de不存在!”;
}
/** *//**
* @return the filepath
*/
public String getFilepath() …{
return filepath;
}
/** *//**
* @param filepath
* the filepath to set
*/
public void setFilepath(String filepath) …{
this.filepath = filepath;
}
/** *//**
* @return the builder
*/
public SAXBuilder getBuilder() …{
return builder;
}
/** *//**
* @param builder
* the builder to set
*/
public void setBuilder(SAXBuilder builder) …{
this.builder = builder;
}
}
3.处理AJAX请求deServlet AddCommentServlet.java
package com.ceun.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ceun.bean.CommentBean;
/** *//**
* <p>后台处理Servlet</p>
*2007-01-30
* * @author ceun
* 联系作者:<br>
* <a href=”mailto:ceun@163.com”>ceun</a><br>
* @version 1.0 2007-01-30 实现基本功能<br>
* */
public class AddCommentServlet extends HttpServlet …{
/** *//**
* serialVersionUID long
*/
private static final long serialVersionUID = 1L;
/** *//**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException …{
request.setCharacterEncoding(”UTF-8″);
response.setContentType(”text/html;charset=UTF-8″);
response.setHeader(”Cache-Control”, “no-cache”);
PrintWriter out = response.getWriter();
String nikename = request.getParameter(”nn”);
String comment = request.getParameter(”rsn”);
String attitude = request.getParameter(”atti”);
String filepath = request.getSession().getServletContext().getRealPath(
“data/comment.xml”);
CommentBean bean = new CommentBean(filepath);
String str = bean.addComment(nikename, comment, attitude);
out.println(str);
}
/** *//**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to
* post.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException …{
doGet(request, response);
}
}