使用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用于文件上传: 更多详细内容 »
转:体验Struts从分页体会MVC
大家都知道Struts是一种基于MVC的结构,而这个MVC又怎么样理解呢?书上阐述的一般都很详细,而我的理解很直白,我们可以把业务逻辑放到每个JSP页面中,当你访问一个JSP页面的时候,就可以看到业务逻辑得到的结果,而把这些业务逻辑与HTML代码夹杂到了一起,一定会造成一些不必要的麻烦,可以不可以不让我们的业务逻辑和那些HTML代码夹杂到一起呢?多少得搀杂一些,那干脆,尽量少的吧,于是我们可以尝试着把业务逻辑的运算过程放到一个Action里,我们访问这个Action,之后Action执行业务逻辑,最后把业务逻辑的结果放到request中,并将页面请求转发给一个用于显示结果的jsp页面,这样,这个页面就可以少去很多的业务逻辑,而只是单纯的去显示一些业务逻辑计算结果的页面而已。这时的Action称为控制器,JSP页可以叫做视图了,而控制器操作的业务对象,无非就应该叫模型了!
从上面的话,我们来分析一下当我们要做一个分页时所需要的部分,而在这之前,我们先看看他们的执行过程吧,首先我们第一次请求访问一个页面,它会把所有记录的前N条显示给我们,之后计算是否有下一页,等类似的信息,当我们点下一页的时候,就获取下一页的信息,我们还可以添加一个搜索,比如我们用于显示学生的,可以安学生姓名查找,学号查找,班级查找。而对于显示的对象,我们一般也都会封装为javabean,所以用于放置查询结果的容器是不定的,而这时,我们就需要用泛型来提升我们的代码效率!
首先我们写一个用于分页显示的javabean: 更多详细内容 »
Tags: 源码Struts版的验证码生成使用方法
[codes=java]
package cn.com.lough.struts.action;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.commons.lang.RandomStringUtils;
/**
* MyEclipse Struts Creation date: 01-11-2007
*
* XDoclet definition:
*
* @struts.action validate="true"
*/
public class ValidatecodeAction extends Action {
/*
* Generated Methods
*/
/**
* Method execute
*
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
*/
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
try {
int width = 50;
int height = 18;
// 取得一个4位随机字母数字字符串
String s = RandomStringUtils.random(4, true, true);
// 保存入session,用于与用户的输入进行比较.
// 注意比较完之后清除session.
HttpSession session = request.getSession(true);
session.setAttribute("validateCode", s);
response.setContentType("images/jpeg");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
ServletOutputStream out = response.getOutputStream();
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
// 设定背景色
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
// 设定字体
Font mFont = new Font("Times New Roman", Font.BOLD, 18);// 设置字体
g.setFont(mFont);
// 画边框
// g.setColor(Color.BLACK);
// g.drawRect(0, 0, width – 1, height – 1);
// 随机产生干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(160, 200));
// 生成随机类
Random random = new Random();
for (int i = 0; i < 155; i++) {
int x2 = random.nextInt(width);
int y2 = random.nextInt(height);
int x3 = random.nextInt(12);
int y3 = random.nextInt(12);
g.drawLine(x2, y2, x2 + x3, y2 + y3);
}
// 将认证码显示到图象中
g.setColor(new Color(20 + random.nextInt(110), 20 + random
.nextInt(110), 20 + random.nextInt(110)));
g.drawString(s, 2, 16);
// 图象生效
g.dispose();
// 输出图象到页面
ImageIO.write((BufferedImage) image, "JPEG", out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Color getRandColor(int fc, int bc) { // 给定范围获得随机颜色
Random random = new Random();
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc – fc);
int g = fc + random.nextInt(bc – fc);
int b = fc + random.nextInt(bc – fc);
return new Color(r, g, b);
}
}
[/codes]
jsp页面的调用
<html:img page="/validatecode.do" border="0" onclick="this.src='/validatecode.do'" alt="请输入此验证码,如看不清请点击刷新。" style="cursor:pointer" />
[codes=javascript]
<script language="JavaScript">
function check(str) {
var s;
var ts;
var tscode;
for (i=0;i<str.length;i++) {
ts=str.substring(i);
tscode=charCodeAt(ts);
if ((tscode<19968)||(ts>40959)) {
alert("you must input chinese");
return false;
}
else {
return true;
}
}
}
</script> [/codes]
charCodeAt()返回字符的unicode代码。
中文字符的代码从4e00-9fff(19968-40959)
监听Session
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package cn.org.jock.http.listener; import java.util.Hashtable; import java.util.Iterator; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * @author jock * */ public class SessionListener implements HttpSessionListener { // 集合对象,保存session 对象的引用 static Hashtable<String,HttpSession> ht = new Hashtable<String,HttpSession>(); // 实现HttpSessionListener接口,完成session创建事件控制 public void sessionCreated(HttpSessionEvent arg0) { HttpSession session = arg0.getSession(); ht.put(session.getId(), session); System.out.println("create session :" + session.getId()); } // 实现HttpSessionListener接口,完成session销毁事件控制 public void sessionDestroyed(HttpSessionEvent arg0) { HttpSession session = arg0.getSession(); System.out.println("destory session :" + session.getId()); ht.remove(session.getId()); } // 返回全部session对象集合 static public Iterator getSet() { return ht.values().iterator(); } // 依据session id返回指定的session对象 static public HttpSession getSession(String sessionId) { return (HttpSession) ht.get(sessionId); } } |
别忘了在web.xml里加上
<listener>
<listener-class>cn.org.jock.http.listener.SessionListener</listener-class>
</listener>
有了这个就可以方便的做很多事了,统计在线人数、在线列表、用户单一登陆等等,自己扩展吧。
Tags: jsp, 技巧, 源码validation.xml示例
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_0.dtd">
<form-validation>
<formset>
<form name="loginForm">
<field depends="required,email" property="email">
<msg name="required" key="error.required"/>
<arg0 key="用户名" resource="false"/>
<msg name="email" key="errors.email"/>
</field>
<field depends="required,minlength,maxlength" property="password">
<msg name="required" key="error.required"/>
<arg0 key="密码" resource="false"/>
<msg name="minlength" key="errors.minlength"/>
<arg0 key="密码" resource="false"/>
<arg1 name="minlength" key="${var:minlength}" resource="false"/>
<var>
<var-name>minlength</var-name>
<var-value>8</var-value>
</var>
<msg name="maxlength" key="errors.maxlength"/>
<arg0 key="密码" resource="false"/>
<arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
<var>
<var-name>maxlength</var-name>
<var-value>16</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
<arg0 key="密码" resource="false"/>指定传给消息文件ApplicationResources.properties文件的对应域的第一个参数内容,resource="false" 不从资源文件读取,相当于直接将“密码”当作第一个参数。
繁体中文到简体中文的转换
[codes=java]
package cn.org.jock.util;
/**
* 编码转换类
* 本类提供两种转换功能:GBK繁体->GBK简体,Big5->GBK简体
*/
import java.io.*;
public class EncodingConvertor
{
/** 转换表所在的目录以 */
private static final String TABLE_FILE_DIR = "converttable";
/** 转换表文件名 */
private static final String BIG5_TO_GBKSIMP_TABLE_FILE_NAME = "big52gb.tab";
//GBK中非GB2312码的汉字编码范围(即可能需要转换的编码范围,GBK-3区和GBK-4区)
//GBK-3区,高字节范围:[0x81, 0xA0];低字节范围:[0x40, 0xFE]
private static int GBK3_HIGH_DOWN = 0×81;
private static int GBK3_HIGH_UP = 0xA0;
private static int GBK3_LOW_DOWN = 0×40;
private static int GBK3_LOW_UP = 0xFE;
//GBK-4区,高字节范围:[0xAA, 0xFE];低字节范围:[0x40, 0xA0]
private static int GBK4_HIGH_DOWN = 0xAA;
private static int GBK4_HIGH_UP = 0xFE;
private static int GBK4_LOW_DOWN = 0×40;
private static int GBK4_LOW_UP = 0xA0;
//Big5编码范围,高字节:[0x81, 0xFE],低字节:[0x40, 0xFE]
private static int BIG5_HIGH_DOWN = 0×81;
private static int BIG5_HIGH_UP = 0xFE;
private static int BIG5_LOW_DOWN = 0×40;
private static int BIG5_LOW_UP = 0xFE;
//是否加载Big5->GBK转换表的Bool值(如果仅仅需要进行GBK繁体->GBK简体的转化,则不必加载Big5->GBK转换表;但Big5->GBK简体转换必须两个表都加载)
private boolean ifloadbig5;
//存放转换表的数组
/**GBK-3区的转换表*/
private byte gbk3table[][][] = new byte[GBK3_HIGH_UP - GBK3_HIGH_DOWN + 1][GBK3_LOW_UP - GBK3_LOW_DOWN + 1][2];
/**GBK-4区的转换表*/
private byte gbk4table[][][] = new byte[GBK4_HIGH_UP - GBK4_HIGH_DOWN + 1][GBK4_LOW_UP - GBK4_LOW_DOWN + 1][2];
/**Big5的转换表*/
private byte big5table[][][] = new byte[BIG5_HIGH_UP - BIG5_HIGH_DOWN + 1][BIG5_LOW_UP - BIG5_LOW_DOWN + 1][2];
/**
* 加载转换表
*
*/
private void loadConvertTables()
{
try
{
DataInputStream dis = new DataInputStream(new FileInputStream(TABLE_FILE_DIR + File.separator + BIG5_TO_GBKSIMP_TABLE_FILE_NAME));
int i, j;
//加载GBK-3区的转换表
for (i = GBK3_HIGH_DOWN; i <= GBK3_HIGH_UP; i ++)
{
for (j = GBK3_LOW_DOWN; j <= GBK3_LOW_UP; j ++)
{
dis.read(gbk3table[i - GBK3_HIGH_DOWN][j - GBK3_LOW_DOWN], 0, 2);
}
}
//加载GBK-4区的转换表
for (i = GBK4_HIGH_DOWN; i <= GBK4_HIGH_UP; i ++)
{
for (j = GBK4_LOW_DOWN; j <= GBK4_LOW_UP; j ++)
{
dis.read(gbk4table[i - GBK4_HIGH_DOWN][j - GBK4_LOW_DOWN], 0, 2);
}
}
dis.close();
if (ifloadbig5)
{
dis = new DataInputStream(new FileInputStream(TABLE_FILE_DIR + File.separator + BIG5_TO_GBKSIMP_TABLE_FILE_NAME));
//加载Big5转换表
for (i = BIG5_HIGH_DOWN; i <= BIG5_HIGH_UP; i ++)
{
for (j = BIG5_LOW_DOWN; j <= BIG5_LOW_UP; j ++)
{
dis.read(big5table[i - BIG5_HIGH_DOWN][j - BIG5_LOW_DOWN], 0, 2);
}
}
dis.close();
}
else
{
big5table = null;
}
}
catch (FileNotFoundException fnfe)
{
fnfe.printStackTrace();
System.exit(-1);
}
catch (IOException ioe)
{
ioe.printStackTrace();
System.exit(-1);
}
}
/**
* 加载转换表
* @param ifbig5 指明是否加载Big5->GBK的转换表
* 如果仅仅需要进行GBK繁体->GBK简体的转化,则不必加载Big5->GBK转换表;但Big5->GBK简体转换必须两个表都加载
*/
public EncodingConvertor(boolean ifbig5)
{
ifloadbig5 = ifbig5;
loadConvertTables();
}
/**
* Big5编码->GBK简体转换的外部调用接口
* 本函数将text[]中的Big5编码的汉字转换成相应GBK编码的简体字,转换后的结果覆盖原来的数组返回
* 不能转换的字符按原值返回
* @param text[] 参数text[]为待转换的字符串的Big5编码的字节数组
* @param textlen textlen为字节个数
*/
public void big52gbk(byte text[], int textlen)
{
//如果没有加载Big5转换表,直接返回
if (!ifloadbig5)
{
return;
}
int i;
int high, low;
i = 0;
while (i < textlen)
{
if (text >= 0)
{
i ++;
continue;
}
if ((i + 1) >= textlen)
{
break;
}
high = text;
high += 0×100;
low = text[i + 1];
if (low < 0)
{
low += 0×100;
}
if ((high >= BIG5_HIGH_DOWN) && (high <= BIG5_HIGH_UP) && (low >= BIG5_LOW_DOWN) && (low <= BIG5_LOW_UP))
{
text = big5table[high - BIG5_HIGH_DOWN][low - BIG5_LOW_DOWN][0];
text[i + 1] = big5table[high - BIG5_HIGH_DOWN][low - BIG5_LOW_DOWN][1];
}
i += 2;
}
}
}
[/codes]
程序中用到的编码表在这里下载。
[sfile]attachment/big52gb.rar[/sfile]
Java版的全角半角转换
注:半角转全角的函数在处理中文的时候会产生乱码。
/**
*
*/
package cn.org.jock.util;
/**
* @author Jock
* @version 1.0
*/
public final class StringUtil {
/**
* DBC case -> SBC case
* 转换中文时会出现问题
* @param DBCstr
* @return
*/
public static final String DBC_to_SBC(String DBCstr) {
StringBuffer outStr = new StringBuffer();
StringBuffer sb = new StringBuffer(DBCstr);
String str = “”;
byte[] b = null;
for (int i = 0; i < DBCstr.length(); i++) {
try {
str = sb.substring(i,i+1);
b = str.getBytes(“unicode”);
} catch (java.io.UnsupportedEncodingException e) {
e.printStackTrace();
}
if (b[3] != -1) {
b[2] = (byte) (b[2] – 32);
b[3] = -1;
try {
outStr.append(new String(b, “unicode”));
} catch (java.io.UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
outStr.append(str);
}
}
return outStr.toString();
}
/**
* SBC case -> DBC case
* @param SBCstr
* @return
*/
public static final String SBC_to_DBC(String SBCstr) {
StringBuffer outStr = new StringBuffer();
String str = “”;
byte[] b = null;
StringBuffer sb = new StringBuffer(SBCstr);
for (int i = 0; i < SBCstr.length(); i++) {
try {
str = sb.substring(i,i+1);
b = str.getBytes(“unicode”);
} catch (java.io.UnsupportedEncodingException e) {
e.printStackTrace();
}
if (b[3] == -1) {
b[2] = (byte) (b[2] + 32);
b[3] = 0;
try {
outStr.append(new String(b, “unicode”));
} catch (java.io.UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
outStr.append(str);
}
}
return outStr.toString();
}
public static void main(String aa[]) {
String sbc = “#?¥%……?*()123半角test”;
String dbc = “#@$%^&*()123半角TEST”;
System.out.println(“半角转换成全角:\”" + dbc + “\” –> \”" + DBC_to_SBC(dbc)+”\”");
System.out.println(“全角转换成半角:\”" + sbc + “\” –> \”" + SBC_to_DBC(sbc)+”\”");
}
}
Java版的MD5编码
[codes=java]
/**
*
*/
package cn.org.jock.util;
import java.security.MessageDigest;
/**
* @author jock
*
*/
public final class MD5 {
/**
* md5 encode
* @param s
* @return
*/
public final static String md5(String s) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };
try {
byte[] strTemp = s.getBytes();
MessageDigest mdTemp = MessageDigest.getInstance(“MD5″);
mdTemp.update(strTemp);
byte[] md = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md;
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
return null;
}
}
/**
* @param args
*/
public static void main(String[] args){
System.out.println(MD5.md5(“ASDASDGFpoF”));
}
}
[/codes]
近期评论