Archive for the ‘ Java ’ Category

基于黑莓平台的MD5密码生成器

前段时间大量密码泄漏的问题闹得挺严重的, 自己也发现我几乎所有网站的注册密码都是相同的. 非常不安全.
如果考虑每个网站使用不同的密码, 对自己来说也是一种负担. 于是就考虑是用md5对自己的密码进行加密.
自己提供一个私钥, 然后输入注册的网站. 之后程序在其中混入数字和符号. 计算md5, 取其中的某几位来生成密码.
这样我只要记住自己的私钥, 那么当我登录weibo的时候, 我的我就在WebSite中写weibo. 这样又好记, 又安全.
我只在自己的黑莓9780上6.0os上测试了, 按道理 96,97应该都能使用.

点击下载: MyMd5Tools - 已下载 25 次

Java循环遍历不定长数组链表

功能描述
一个链表中保存多个不同长度的数组, 根据一个索引值, 能取到对应的元素所在的数组下标

public static int[] calcIndexArr(final List<String[]> list, int index) {
    int listSize;
    if (list == null || (listSize = list.size()) == 0) {
        return new int[0];
    }

    int max = 1;
    for (int i = 0; i < list.size(); i++) {
        max *= list.get(i).length;
    }
    while (index >= max) {
        index -= max;
    }

    int[] indexArr = new int[list.size()];

    for (int i = 0; i < listSize; i++) {
        int b = 1;
        for (int j = i + 1; j < listSize; j++) {
            b *= list.get(j).length;
        }
        int a = index / b;
        indexArr[i] = a;
        index = index - a * b;
    }
    return indexArr;
}

测试方法:

public void testCalcIndexArr() {
    List<String[]> list = new ArrayList<String[]>();
    list.add(new String[2]);
    list.add(new String[4]);
    list.add(new String[1]);
    for (int i = 0; i < 30; i++) {
        int arr[] = RandName.calcIndexArr(list, i);
        assertEquals(3, arr.length);
        System.out.println(arr[0] + "," + arr[1] + "," + arr[2]);
    }
}

测试结果

0,0,0
0,1,0
0,2,0
0,3,0
1,0,0
1,1,0
1,2,0
1,3,0
0,0,0
0,1,0
0,2,0
0,3,0
1,0,0
1,1,0
1,2,0
1,3,0
0,0,0
0,1,0
0,2,0
0,3,0
1,0,0
1,1,0
1,2,0
1,3,0
0,0,0
0,1,0
0,2,0
0,3,0
1,0,0
1,1,0

解决Jsp插入Mysql,设置UTF8依然乱码问题

问题描述:
JSP网页里是charset=UTF-8: 

<%@ page contentType= “text/html; charset=UTF-8 ” language= “java ” import= “java.sql.* ” errorPage= “error.jsp ” %> 

Mysql5里存取的数据库的charset也设成了UTF-8,可是通过JSP网页存取中文还是显示乱码 

解决方案:加个过滤类 

package com.bx.util; 

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; 

public class SetEncodingFilter implements Filter { 

    // ----------------------------------------------------- Instance  Variables 

    /**
     * The default character encoding to set for requests that pass through this
     * filter.
     */
    protected String encoding = null; 

    /**
     * The filter configuration object we are associated with. If this value is
     * null, this filter instance is not currently configured.
     */
    protected FilterConfig filterConfig = null; 

    /**
     * Should a character encoding specified by the client be ignored?
     */
    protected boolean ignore = true; 

    // --------------------------------------------------------- Public Methods 

    /**
     * Take this filter out of service.
     */
    public void destroy() {
        this.encoding = null;
        this.filterConfig = null;
    } 

    /**
     * Select and set (if specified) the character encoding to be used to
     * interpret request parameters for this request.
     *
     * @param request
     * The servlet request we are processing
     * @param result
     * The servlet response we are creating
     * @param chain
     * The filter chain we are processing
     *
     * @exception IOException
     * if an input/output error occurs
     * @exception ServletException
     * if a servlet error occurs
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // Conditionally select and set the character encoding to be used
        if (ignore || (request.getCharacterEncoding() == null)) {
            String encoding = selectEncoding(request);
            if (encoding != null) {
                request.setCharacterEncoding(encoding);
            }
        } 

        // Pass control on to the next filter
        chain.doFilter(request, response);
    } 

    /**
     * Place this filter into service.
     *
     * @param filterConfig
     * The filter configuration object
     */
    public void init(FilterConfig filterConfig) throws ServletException { 

        this.filterConfig = filterConfig;
        this.encoding = filterConfig.getInitParameter("encoding");
        String value = filterConfig.getInitParameter("ignore");
        if (value == null) {
            this.ignore = true;
        } else if (value.equalsIgnoreCase("true")) {
            this.ignore = true;
        } else if (value.equalsIgnoreCase("yes")) {
           this.ignore = true;
        } else {
           this.ignore = false;
        }
    } 

    // ------------------------------------------------------ Protected Methods 

    /**
     * Select an appropriate character encoding to be used, based on the
     * characteristics of the current request and/or filter initialization
     * parameters. If no character encoding should be set, return
     * <code>null</code>.
     * <p>
     * The default implementation unconditionally returns the value configured
     * by the <strong>encoding</strong> initialization parameter for this
     * filter.
     *
     * @param request
     * The servlet request we are processing
     */
    protected String selectEncoding(ServletRequest request) {
        return (this.encoding);
    }
}

然后在web.xml文件中配置一下就可以了 

<filter>
    <filter-name>Set Character Encoding</filter-name>
    <filter-class>com.bx.util.SetEncodingFilter类的路径</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>Set Character Encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

测试PreparedStatement的批处理效率

今天研究了一下Java中PreparedStatement的批处理能力.

测试环境如下:

jdk1.6.0_21 +Mysql 5.1

Core 2 Duo T5470 (1.60GHz) + 3G内存

测试的是实现最简单的插入:

INSERT INTO `testdb` (`id`, `value`) VALUES (123456, ‘http://www.pptv.com’)

共插入20万条数据, 每个测试前都把数据库清空, 然后执行插入, 从开始插入进行计时.每项测试跑3次取平均值.

分为两项测试: 1个是不使用批处理, 逐条插入; 一个是使用addBatch(), 分别按50, 100, 500, 1000, 5000, 10000, 50000, 100000的划分方式进行批量插入. 关键代码如下:

逐行插入:

for (int times = 0; times &lt; TEST_TIMES; times++) {
    cleanDB();
    conn = DBMgr.getDBconn(&quot;testdb&quot;);
    long starttime = System.currentTimeMillis();
    for (int i = 0; i &lt; MAX_COUNT; i++) {
        pstmt = conn.prepareStatement(SQL);
        pstmt.executeUpdate();
        pstmt.close();
        System.out.println(&quot;working: &quot; + i + &quot;/&quot; + MAX_COUNT);
    }
    long endtime = System.currentTimeMillis();
    LOG.info(&quot;第&quot; + (times + 1) + &quot;次测试, 耗时&quot; + (endtime - starttime) + &quot;ms&quot;);
    alltime += endtime - starttime;
}
LOG.info(&quot;平均耗时: &quot; + (alltime / TEST_TIMES) + &quot;ms&quot;);

批处理操作

for (int times = 0; times &lt; TEST_TIMES; times++) {
    cleanDB();
    conn = DBMgr.getDBconn(&quot;testdb&quot;);
    conn.setAutoCommit(false);
    int num = 0;
    long starttime = System.currentTimeMillis();
    pstmt = conn.prepareStatement(SQL);
    for (int i = 0; i &lt; MAX_COUNT; i++) {
        pstmt.addBatch();
        num++;
        if (num % count == 0 || num == MAX_COUNT) {
            pstmt.executeBatch();
            pstmt.clearBatch();
            pstmt.close();
            pstmt = conn.prepareStatement(SQL);
        }
        System.out.println(&quot;working: &quot; + i + &quot;/&quot; + MAX_COUNT);
    }
    long endtime = System.currentTimeMillis();
    LOG.info(&quot;第&quot; + (times + 1) + &quot;次测试, 耗时&quot; + (endtime - starttime) + &quot;ms&quot;);
    alltime += endtime - starttime;
}
LOG.info(&quot;平均耗时: &quot; + (alltime / TEST_TIMES) + &quot;ms&quot;);

记录的log如下:

11:59:25,703 DBTestMulti test  *** 以100000为一次批量操作, 执行批处理语句  ***
11:59:25,703 BaseDBTest cleanDB 初始化数据库
11:59:58,984 DBTestMulti test 第1次测试, 耗时33000ms
11:59:58,984 BaseDBTest cleanDB 初始化数据库
12:01:21,687 DBTestMulti test 第2次测试, 耗时32594ms
12:01:21,687 BaseDBTest cleanDB 初始化数据库
12:02:44,640 DBTestMulti test 第3次测试, 耗时32562ms
12:02:44,640 DBTestMulti test 平均耗时: 32718ms
12:02:47,093 DBTestMulti test  *** 以50000为一次批量操作, 执行批处理语句  ***
12:02:47,093 BaseDBTest cleanDB 初始化数据库
12:03:19,734 DBTestMulti test 第1次测试, 耗时32625ms
12:03:19,734 BaseDBTest cleanDB 初始化数据库
12:04:43,406 DBTestMulti test 第2次测试, 耗时33328ms
12:04:43,406 BaseDBTest cleanDB 初始化数据库
12:06:06,687 DBTestMulti test 第3次测试, 耗时32609ms
12:06:06,687 DBTestMulti test 平均耗时: 32854ms
12:06:09,125 DBTestMulti test  *** 以10000为一次批量操作, 执行批处理语句  ***
12:06:09,125 BaseDBTest cleanDB 初始化数据库
12:06:40,921 DBTestMulti test 第1次测试, 耗时31781ms
12:06:40,921 BaseDBTest cleanDB 初始化数据库
12:08:03,125 DBTestMulti test 第2次测试, 耗时32032ms
12:08:03,125 BaseDBTest cleanDB 初始化数据库
12:09:26,859 DBTestMulti test 第3次测试, 耗时32781ms
12:09:26,859 DBTestMulti test 平均耗时: 32198ms
12:09:29,296 DBTestMulti test  *** 以5000为一次批量操作, 执行批处理语句  ***
12:09:29,296 BaseDBTest cleanDB 初始化数据库
12:10:00,406 DBTestMulti test 第1次测试, 耗时31094ms
12:10:00,406 BaseDBTest cleanDB 初始化数据库
12:11:23,031 DBTestMulti test 第2次测试, 耗时31953ms
12:11:23,031 BaseDBTest cleanDB 初始化数据库
12:12:46,265 DBTestMulti test 第3次测试, 耗时32187ms
12:12:46,265 DBTestMulti test 平均耗时: 31744ms
12:12:48,718 DBTestMulti test  *** 以1000为一次批量操作, 执行批处理语句  ***
12:12:48,718 BaseDBTest cleanDB 初始化数据库
12:13:20,468 DBTestMulti test 第1次测试, 耗时31750ms
12:13:20,468 BaseDBTest cleanDB 初始化数据库
12:14:43,703 DBTestMulti test 第2次测试, 耗时32625ms
12:14:43,703 BaseDBTest cleanDB 初始化数据库
12:16:06,203 DBTestMulti test 第3次测试, 耗时32125ms
12:16:06,203 DBTestMulti test 平均耗时: 32166ms
12:16:08,656 DBTestMulti test  *** 以500为一次批量操作, 执行批处理语句  ***
12:16:08,656 BaseDBTest cleanDB 初始化数据库
12:16:40,906 DBTestMulti test 第1次测试, 耗时32235ms
12:16:40,906 BaseDBTest cleanDB 初始化数据库
12:18:03,625 DBTestMulti test 第2次测试, 耗时32547ms
12:18:03,625 BaseDBTest cleanDB 初始化数据库
12:19:27,343 DBTestMulti test 第3次测试, 耗时33265ms
12:19:27,343 DBTestMulti test 平均耗时: 32682ms
12:19:30,406 DBTestMulti test  *** 以100为一次批量操作, 执行批处理语句  ***
12:19:30,406 BaseDBTest cleanDB 初始化数据库
12:20:53,875 DBTestMulti test 第1次测试, 耗时32782ms
12:20:53,875 BaseDBTest cleanDB 初始化数据库
12:22:17,765 DBTestMulti test 第2次测试, 耗时33687ms
12:22:17,765 BaseDBTest cleanDB 初始化数据库
12:23:41,609 DBTestMulti test 第3次测试, 耗时33531ms
12:23:41,609 DBTestMulti test 平均耗时: 33333ms
12:23:44,421 DBTestMulti test  *** 以50为一次批量操作, 执行批处理语句  ***
12:23:44,421 BaseDBTest cleanDB 初始化数据库
12:25:07,578 DBTestMulti test 第1次测试, 耗时32500ms
12:25:07,578 BaseDBTest cleanDB 初始化数据库
12:26:31,796 DBTestMulti test 第2次测试, 耗时33718ms
12:26:31,796 BaseDBTest cleanDB 初始化数据库
12:27:55,640 DBTestMulti test 第3次测试, 耗时33562ms
12:27:55,640 DBTestMulti test 平均耗时: 33260ms
12:27:58,468 BaseDBTest cleanDB 初始化数据库
14:08:25,484 DBTestSingle test 第1次测试, 耗时5976406ms
14:08:25,484 BaseDBTest cleanDB 初始化数据库
15:47:18,828 DBTestSingle test 第2次测试, 耗时5882735ms
15:47:18,828 BaseDBTest cleanDB 初始化数据库

其中批处理都是执行3次取平均值, 而逐行操作, 一次执行时间就要1个半小时, 所以只跑了两次. 日志筛选如下:

每次100000条, 分2次处理: 32718ms

每次50000条, 分4次处理: 32854ms

每次10000条, 分20次处理: 32198ms

每次5000条, 分40次处理: 31744ms

每次1000条, 分200次处理: 32166ms

每次500条, 分400次处理: 32682ms

每次100条, 分2000次处理: 33333ms

每次50条, 分4000次处理: 33260ms

而最后的两条是没有使用批处理跑出来的 用时近600000ms, 近1小时40分钟, 完全不是一个数量级的.

相比较而言, 批处理语句在量的划分上差别并不明显, 在千级的划分只有一点点的减少.

详细测试间测试代码(已上传).

点击下载: db-batch-test - 已下载 214 次

解决JDK1.6下SunJCE() is not accessible问题

一个老的项目从JDK1.5迁移到1.6时, Eclipse抛出一堆错误 主要是:

Access restriction: The constructor SunJCE() is not accessible due to restriction on required library /pp/develop/install/jdk1.6.0_21/jre/lib/ext/sunjce_provider.jar

访问限制: 由于/pp/develop/install/jdk1.6.0_21/jre/lib/ext/sunjce_provider.jar库的限制, SunJCE() 构造函数不可访问.

在网上搜了一下, 解决办法是修改编译选项, 方法如下: Window ->Preferences -> Java -> Compiler -> Errors/Warnings -> Deprecated and restricted API -> Forbidden reference (access rules) -> Warnings或者Ignore即可.