当柳上原的风吹向天际的时候...

真正的快乐来源于创造

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks

#

PNG图片作为网页图的一个好处是它允许有透明背景,这一点比gif格式做得要好,但也有不如意的地方,就是在FireFox上PNG的透明背景显示得很好,但是在IE中就做不到了,这就需要滤镜技术的帮助。

比如有一张图片作为logo,它放在一个id为logodiv的DIV中,在CSS中是这样定义的:
#logoDiv{
    width
:300px;
    height
:100%;
    background
:transparent url(../img/logo.png) no-repeat -65px 0px;
}

这张图片在FF显示没有问题,在IE6中就需要加上这样一段:
*html #logoDiv{
    width
:300px;
    height
:100%;
    margin-left
:-65px;
    background-color
:transparent;
    background-image
:none;
    filter
:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="web/img/logo.png", sizingMethod="crop");
}
这段代码FireFox是不认识的,会被略过,图片会继续上面#logoDiv的效果,而IE会用下面一段取代上面这一段,所以滤镜透明图片的效果就出现了。这两段代码放在一起,无论客户浏览器是IE6或是FireFox都能适应了。

使用滤镜有两点需要注意的:一是图片地址是网页相对app的地址,不是css相对app的地址,所以上面两处路径会有差异;另外一点是在不同的IE滤镜的写法也有差异,需要根据客户浏览器实际情况调整一下。

具体代码请见,其中有三处使用了滤镜,分别是logo,主菜单左侧和右侧,您可以从下面的代码中去寻找它们
http://www.box.net/shared/tz5k1um68l
http://www.box.net/shared/mbdf2e85yi



posted @ 2011-03-04 13:13 何杨 阅读(907) | 评论 (0)编辑 收藏

说明:下文涉及的内容只限于对前端jsp和后台servlet的代码修改,不涉及Web容器和数据库的相关修改。
我的测试环境是:英文XP操作系统,容器采用Tomcat6,前台是jsp,后台Servlet,Ajax框架采用prototype1.6.0

Web编程中前后端乱码问题发生的根源
从前端jsp到后台的Servlet,中间传输过程中的默认编码方式是ISO-8859-1,这种编码方式是西欧字符集,包括英语,德语,丹麦语,芬兰语等,其它语言如中文日文等是不兼容的,如不经转换或是设置直接在Servlet中用request.getParameter(paramName)这种方式直接拿出来中文部分就会得到乱码,但英语,字母,数字组合成的字符串是不会变成乱码的。

常见的编码解决乱码问题的方式有
  • new String(request.getParameter(paramName).getBytes("ISO-8859-1"),"页面字符集");
  • HttpServletRequest.setCharacterEncoding("页面字符集");
  • URLDecoder.decode(str, "UTF-8");
它们各自用在不同的场合,这里的页面字符集指GBK,GB2312,UTF-8等,它们通常和jsp页面设定的字符集(charset)一致。

如果是将form通过post方式提交,在servlet的doPost函数开头(对于Struts写在execute函数开头)写上request.setCharacterEncoding("jsp网页字符集")就可以直接用request.getParameter(paramName)直接得到文字,不需要经过再转码。这里需要注意的是form的action如果不直接写成post的话,是会以get方式提交,这时request.setCharacterEncoding就会失效。

如果不管是post还是get方式,想做一个通用方案,则可以通过new String(request.getParameter(paramName).getBytes("ISO-8859-1"),"jsp网页编码方式")得到转码后正常的文字,这种方式只要知道网页的字符集,几乎都能还原成正确的文字,适用性很广,在Servlet和Action中很常见。

如果是Ajax提交方式,则在servlet或是action中书写request.setCharacterEncoding("jsp网页字符集")是没有效果的,经过对提交的URL用一次javascript的encodeURI函数编码后,用 new String(request.getParameter(paramName).getBytes("ISO-8859-1"),"jsp网页字符集")可以得到正确的文字。但如果不用encodeURI函数处理提交的url则不会正确的文字。

Ajax提交中文的另一种方式可以用javascript的encodeURI函数对提交的URL进行两次编码,而后台采用URLDecoder.decode(request.getParameter(paramName), "UTF-8")得到正确的文字。

上面两种方式都借助了avascript的encodeURI函数的帮助,它能将字符串进行utf-8编码,其中,第二种方式确定性很高,推荐。

具体方式请参考下面给出的例程,里面含有12个例子,分别对应了多种情况:
http://www.blogjava.net/Files/heyang/DisorderCode2011-01-31.zip



参考文章:
深入浅出 web 编码(转载整理)
http://www.blogjava.net/heyang/archive/2011/01/26/343570.html
posted @ 2011-01-30 18:07 何杨 阅读(1836) | 评论 (0)编辑 收藏

以下代码主体来自互联网,原作者已经不可考,在此向这些有共享精神的作者致敬。

一.日期的合法性校验
以下代码中进行验证的主函数是isValidDateString,它的输入是类似2011-1-27这样的字符串,如果合法就返回真,否则返回假。如果您的日期格式不同,请将验证主函数中的正则表达式修改之,比如说输入是2011/1/27这样的字符串,则pattern=/^ *(\d{4})[/](\d{1,2})[/](\d{1,2})*$/;
// 进行日期合法性验证的主函数
function
 isValidDateString(dateString){
    
var pattern=/^ *(\d{4})-(\d{1,2})-(\d{1,2})*$/;
    
var arr=pattern.exec(dateString);
    
   
var year=arr[1];
    
var month=arr[2];
    
var dday=arr[3];

    
return IsValidDate(year,month,dday);
}


function IsValidYear(psYear)
{
    
var sYear = new String(psYear);


    
if(psYear==null)
    {
        
return false;
    }


    
if(isNaN(psYear)==true)
    {
        
return false;
    }

    
if(sYear == "")
    {
        
return true;
    }

    
if(sYear.match(/[^0-9]/g)!=null)
    {
        
return false;
    }

    
var nYear = parseInt(sYear, 10);

    
if((nYear < 0|| (9999 < nYear))
    {
        
return false;
    }

    
return true;
}


function IsValidMonth(psMonth)
{
    
var sMonth = new String(psMonth);

    
if(psMonth==null)
    {
        
return false;
    }

    
if(isNaN(psMonth)==true)
    {
        
return false;
    }

    
if(sMonth == "")
    {
        
return true;
    }

    
if(sMonth.match(/[^0-9]/g)!=null)
    {
        
return false;
    }

    
var nMonth = parseInt(sMonth,10);

    
if((nMonth < 0|| (12 < nMonth))
    {
        
return false;
    }

    
return true;
}


function IsValidDay(psDay)
{
    
var sDay  = new String(psDay);

    
if(psDay==null)
    {
        
return false;
    }

    
if(isNaN(psDay)==true)
    {
        
return false;
    }

    
if(sDay == "")
    {
        
return true;
    }

    
if(sDay.match(/[^0-9]/g)!=null)
    {
        
return false;
    }

    
var nDay = parseInt(psDay, 10);

    
if((nDay < 0|| (31 < nDay))
    {
        
return false;
    }

    
return true;
}


function IsValidDate(psYear, psMonth, psDay)
{
    
if(psYear==null || psMonth==null || psDay==null)
    {
        
return false;
    }

    
var sYear  = new String(psYear);
    
var sMonth = new String(psMonth);
    
var sDay   = new String(psDay);

    
if(IsValidYear(sYear)==false)
    {
        
return false;
    }

    
if(IsValidMonth(sMonth)==false)
    {
        
return false;
    }

    
if(IsValidDay(sDay)==false)
    {
        
return false;
    }

    
var nYear  = parseInt(sYear,  10);
    
var nMonth = parseInt(sMonth, 10);
    
var nDay   = parseInt(sDay,   10);

    
if(sYear=="" &&  sMonth=="" && sDay=="")
    {
        
return true;
    }

    
if(sYear=="" || sMonth=="" || sDay=="")
    {
        
return false;
    }
   
    
if(nMonth < 1 || 12 < nMonth)
    {
        
return false;
    }
    
if(nDay < 1 || 31 < nDay)
    {
        
return false;
    }

    
if(nMonth == 2)
    {
        
if((nYear % 400 == 0|| (nYear % 4 == 0&& (nYear % 100 != 0))
        {
            
if((nDay < 1|| (nDay > 29))
            {
                
return false;
            }
        }
        
else
        {
            
if((nDay < 1|| (nDay > 28))
            {
                
return false;
            }
        }
    }
    
else if((nMonth == 1)  ||
            (nMonth 
== 3)  ||
            (nMonth 
== 5)  ||
            (nMonth 
== 7)  ||
            (nMonth 
== 8)  ||
            (nMonth 
== 10||
            (nMonth 
== 12))
    {
        
if((nDay < 1|| (31 < nDay))
        {
            
return false;
        }
    }
    
else
    {
        
if((nDay < 1|| (30 < nDay))
        {
            
return false;
        }
    }

    
return true;
}


二.日期的比较
下面函数是进行日期比较如果date1小于等于date2,则返回真,否则返回假。注意这两个参数都应该通过了上面的日期合法性校验,请注意先验证一下。
function isReasonable(startDate,endDate){

    startDate=startDate.replace("-","/");
    endDate=endDate.replace("-","/");

    var dt1=new Date(Date.parse(startDate));
    var dt2=new Date(Date.parse(endDate));
      
    return dt1<=dt2;
}

posted @ 2011-01-27 16:51 何杨 阅读(876) | 评论 (3)编辑 收藏

在Ajax程序中,在URL拼接时带有中文参数是不可避免的事情,如
var url='/YourAppName/CreateTodo.do?name='+name;
其中name是来自inputbox的取值,它可能带有中文。

如果让Ajax直接提交这样的URL,那么后台用request.getParameter("name");这样的方法得到的name就会含有乱码。

解决之道是先对URL进行两次编码,用的是JavaScript的encodeURI函数,具体代码如下:
var url=encodeURI('/YourAppName/CreateTodo.do?name='+name);
url
=encodeURI(url);

在后台的Servlet或是Action中,可以这样得到正确的文字:
Sting name=java.net.URLDecoder.decode(request.getParameter("name"),"utf-8");

就是这样,值得注意的是,中文环境的机器用容器跑WebApp也许不需要这样的处理,但其它环境如日文,英文就非此不可了,因此在编码时尽可能这样处理一下,如果安装后出现问题就会造成慌乱了。我们在编写Web程序时,最好让文件编码,数据库编码,输出编码,网页编码保持一致,这样能省去很多麻烦。

以上操作的具体原理请见:
http://yiminghe.javaeye.com/blog/243812
http://yiminghe.javaeye.com/blog/247837

posted @ 2011-01-26 14:46 何杨 阅读(2055) | 评论 (1)编辑 收藏

已有功能:
进行混合加密的消息传递,用户注册,登录,取RSA公钥,得到用户列表,通过服务器中转消息。

修正点:
1.针对较长文字改变了解析方式。
2.聊天界面又向QQ靠拢了一些。

下载地址:
http://www.blogjava.net/Files/heyang/IMSample2011-01-25-1320.zip

界面截图:



posted @ 2011-01-25 13:18 何杨 阅读(237) | 评论 (2)编辑 收藏

一般说的组合键,是指在按下某个特定的键的时候,有另一些键处于某个特定的状态。例如:按回车enter,且CTRL键处于按下的状态,就认为是按了CTRL+回车这个组合键。

下面是具体的代码,myTextArea是一个文本区域组件(JTextArea)。注意其中粗体部分:
myTextArea.addKeyListener(new KeyListener(){
            @Override
            
public void keyReleased(KeyEvent arg0) {
                 
if ( arg0.getKeyCode() == KeyEvent.VK_ENTER && 
                    ((arg0.getModifiersEx() 
& KeyEvent.CTRL_DOWN_MASK) != 0) && 
                    ((arg0.getModifiersEx() 
& KeyEvent.SHIFT_DOWN_MASK) == 0)   ) {
                         
//   do something......
                 }
            }
            
            @Override
            
public void keyPressed(KeyEvent arg0) {
                
// do nothing
                
            }

            @Override
            
public void keyTyped(KeyEvent arg0) {
                
// do nothing
                
            }
        });
上面粗体部分第一句意味着回车键处于按下状态;
第二句意味着同时Ctrl键处于按下状态;
第三句意味着Shift键没有处于按下状态;
整个条件就是指在ctrl+enter键按下时,执行特定的处理。

Java文本组件中检测组合键就是这样简单。
posted @ 2011-01-25 11:24 何杨 阅读(504) | 评论 (0)编辑 收藏

下载地址:
http://www.box.net/shared/ccymfosmyu

本版改善功能:
1.客户端界面朝QQ靠近了点。
2.去除了发送信息时的一个潜在隐患。

posted @ 2011-01-24 21:39 何杨 阅读(174) | 评论 (1)编辑 收藏

myFrame.setExtendedState(JFrame.NORMAL);
myFrame.toFront();

myFrame是从Swing的JFame继承而来的类。

posted @ 2011-01-24 17:07 何杨 阅读(982) | 评论 (0)编辑 收藏

       // 设定布局
        int gridx, gridy, gridwidth, gridheight, anchor, fill, ipadx, ipady;
        
double weightx, weighty;
        GridBagConstraints c;
        Insets inset;
        GridBagLayout gridbag 
= new GridBagLayout();
        
this.setLayout(gridbag);
        
        
// 0,0
        gridx = 0;
        gridy 
= 0;
        gridwidth 
= 1;
        gridheight 
= 1;
        weightx 
= 1.00;
        weighty 
= 1.00;
        anchor 
= GridBagConstraints.CENTER;
        fill 
= GridBagConstraints.BOTH;
        inset 
= new Insets(up, left, down, right);
        ipadx 
= 0;
        ipady 
= 0;
        c 
= new GridBagConstraints(gridx, gridy, gridwidth, gridheight,
                weightx, weighty, anchor, fill, inset, ipadx, ipady);
        JScrollPane js
=new JScrollPane(msgArea);
        gridbag.setConstraints(js, c);
        
this.add(js);

        以上代码中,Insets构造函数四个参数的顺序依次为上,左,下,右, 逆时针方向。这样比较好记忆。
        Swing中其它类似的四参数形式(如BorderFactory.createEmptyBorder(top, left, down, right))也类同此例。

posted @ 2011-01-24 15:00 何杨 阅读(3232) | 评论 (0)编辑 收藏

将文字在网络中进行传输的时候,如果存在非ASCII码字符,很容易出现乱码问题,要解决也不难,在传输的文字上用URLEncoder进行编码,将它变成全部是ASCII码的形式,这样在网络传输中就不会受到影响;在另一侧,将收到的文字用URLDecoder加码就能还原文字原本的摸样。

IMSample中涉及到文字的混合加密,情况稍复杂一点,但流程还是一样的。


相关涉及编码和解码的工具类:
package com.heyang.common.code;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;


/**
 * UTF8转码器
 * 
@author heyang
 *
 
*/
public class UTF8Coder{
    
private static final String UTF_8 = "utf-8";// 编码形式

    
/**
     * 对文字进行UTF8转码
     * 
@param str
     * 
@return
     
*/
    
public static String encode(String str){
        
try {
            
return URLEncoder.encode(str, UTF_8);
        } 
catch (UnsupportedEncodingException e) {
            
return null;
        }
    }
    
    
/**
     * 将转码后的文字还原
     * 
@param str
     * 
@return
     
*/
    
public static String decode(String str){
        
try {
            
return URLDecoder.decode(str, UTF_8);
        } 
catch (UnsupportedEncodingException e) {
            
return null;
        }
    }
}

变化后的加密器代码:
package com.heyang.common.cipher;

import org.apache.commons.codec.binary.Base64;

import com.heyang.common.code.AESSecurityCoder;
import com.heyang.common.code.Base64SecurityUtil;
import com.heyang.common.code.RSASecurityCoder;
import com.heyang.common.code.UTF8Coder;

/**
 * 对消息进行加密的加密器
 * 说明:
 * 作者:何杨(heyang78@gmail.com)
 * 创建时间:2010-12-27 下午07:00:29
 * 修改时间:2010-12-27 下午07:00:29
 
*/
public class IMMsgEncrypter{
    
// 经加密的消息
    private String cipheredMsg;
    
    
/**
     * 构造函数
     * 
@param plainMsg 未加密的消息
     * 
@param otherSideRSAPublicKey 对方RSA公钥
     * 
@param rsaCoder 己方RSA编码器
     * 
@param aesCoder 己方AES编码器
     * 
@throws IMMsgEncryptException
     
*/
    
public IMMsgEncrypter(String plainMsg,String otherSideRSAPublicKey,RSASecurityCoder rsaCoder,AESSecurityCoder aesCoder) throws IMMsgEncryptException{
        
try{
            
// 防止乱码
            plainMsg=UTF8Coder.encode(plainMsg);
            
            
// 对明文进行AES加密
            byte[] aesArr=aesCoder.getEncryptByteArray(plainMsg); // 对明文进行AES加密
            String cipherText=Base64.encodeBase64String(aesArr);// 得到AES加密后的密文
            
            
// 使用RSA对AES密钥进行加密
            String key=aesCoder.getAesKey();// 取得AES的密钥
            String aesKey="";
            
try{
                
byte[] clientRsaKeyArr=null;
                clientRsaKeyArr
=Base64.decodeBase64(otherSideRSAPublicKey);
                
byte[] rsaArr=rsaCoder.getEncryptArray(key, clientRsaKeyArr);
                aesKey
=Base64.encodeBase64String(rsaArr);
            }
            
catch(Exception ex){
                
throw new IMMsgEncryptException("使用对方RSA公钥加密己方AES钥匙时发生异常.");
            }
            
            
// 在发出的密文前附带经服务器RSA公钥加密的AES密钥
            StringBuilder sb=new StringBuilder();
            sb.append(
"<aeskey>"+aesKey+"</aeskey>");
            sb.append(
"<rsakey>"+rsaCoder.getPublicKeyString()+"</rsakey>");
            sb.append(
"<text>"+cipherText+"</text>");
            
            
// 最后对整体进行Base64加密
            cipheredMsg=Base64SecurityUtil.getEncryptString(sb.toString());
        }
        
catch(Exception ex){
            
throw new IMMsgEncryptException("加密消息时发生异常,异常信息为"+ex.getMessage()+".");
        }
    }

    
public String getCipheredMsg() {
        
return cipheredMsg;
    }
}

修改后的解码器代码:
package com.heyang.common.cipher;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.codec.binary.Base64;

import com.heyang.common.code.AESSecurityCoder;
import com.heyang.common.code.Base64SecurityUtil;
import com.heyang.common.code.RSASecurityCoder;
import com.heyang.common.code.UTF8Coder;


/**
 * 消息解密器
 * 说明:
 * 作者:何杨(heyang78@gmail.com)
 * 创建时间:2010-12-27 下午07:41:44
 * 修改时间:2010-12-27 下午07:41:44
 
*/
public class IMMsgDecrypter{
    
// 固定的三个节点名
    private static final String TEXT = "text";

    
private static final String RSAKEY = "rsakey";

    
private static final String AESKEY = "aeskey";

    
// 对方的RSA公钥
    private String otherSideRSAPublicKey;
    
    
// 解密后的明文
    private String plainMsg;
    
    
/**
     * 构造函数
     * 
@param cipherMsg 要解密的消息
     * 
@param rsaCoder 己方RSA编码器
     * 
@param aesCoder 己方AES编码器
     * 
@throws IMMsgDecryptException
     
*/
    
public IMMsgDecrypter(String cipherMsg,RSASecurityCoder rsaCoder,AESSecurityCoder aesCoder) throws IMMsgDecryptException{
        
try{
            
// 先用Base64解密密文
            cipherMsg=Base64SecurityUtil.getDecryptString(cipherMsg);
            
            
// 用正则表达式得到密钥文,客户端的RSA公钥和密文
            String regex="<(\\w+)>((.|\\s)+)</\\1>";

            Pattern pattern
=Pattern.compile(regex);
            Matcher matcher
=pattern.matcher(cipherMsg);
                
            String cipheredAesKey
="";// 经服务器RSA公钥加密的客户端AES钥匙密文
            String cipherText="";// 经客户端AES加密的密文
            
            Map
<String,String> map=new HashMap<String,String>();
            
while(matcher.find()){
                map.put(matcher.group(
1), matcher.group(2));
            }
            
            
if(map.size()==3){
                cipheredAesKey
=map.get(AESKEY);
                otherSideRSAPublicKey
=map.get(RSAKEY);
                cipherText
=map.get(TEXT);
            }
            
else{
                
throw new IMMsgDecryptException("解密消息时发生异常,原因是消息格式不正确.消息为:"+cipherMsg);
            }

            
// 得到经过服务器RSA私钥解密后的AES密钥
            String plainAesKey="";
            
try {
                
byte[] cipheredAesKeyArr=Base64.decodeBase64(cipheredAesKey);
                plainAesKey
=rsaCoder.getDecryptString(cipheredAesKeyArr);
            } 
catch (Exception e) {
                
throw new IMMsgDecryptException("无法解密对方AES密钥,异常信息为"+e.getMessage()+",客户端请求为:"+cipherMsg);
            }
            
            
// 使用AES密钥解密出明文
            byte[] cipherTextArr=Base64.decodeBase64(cipherText);
            plainMsg
=aesCoder.getDecryptString(cipherTextArr, plainAesKey);
            
            
//  UTF08还原
            plainMsg=UTF8Coder.decode(plainMsg);
        }
        
catch(Exception ex){
            
throw new IMMsgDecryptException("解密消息发生异常,异常信息为"+ex.getMessage()+".");
        }
    }

    
public String getOtherSideRSAPublicKey() {
        
return otherSideRSAPublicKey;
    }

    
public String getPlainMsg() {
        
return plainMsg;
    }
}

以上只是涉及乱码问题的一个处理方法,各位还要具体情况具体分析。
posted @ 2011-01-21 22:41 何杨 阅读(250) | 评论 (0)编辑 收藏

仅列出标题
共28页: First 上一页 11 12 13 14 15 16 17 18 19 下一页 Last