编写更少量的代码

在看项目代码的过程中你会发现某些代码完全可以直接用开源框架来减少代码量的,如一些带有until的工具类、一些常用的io操作等;

研究发现一般的应用程序每 1,000 行代码就包含 20 到 250 个 bug!这个度量被称作缺陷密度。因此可得出一个重要的结论:更少的代码意味着更少的缺陷。

个人认为在项目开发过程中最好能有这样的习惯:能用开源框架(开源框架基本都是众多程序员智慧的结晶,经得住考验)就尽量用,最大限度地减少编码量;即当编码处理一些业务逻辑时首先想想或找找有没相关的开源框架,有适合的就用。

重视Apache Commons

公司的各个应用下基本都有Apache Commons下的一些jar包,但在开发过程中习惯性用到这些工具包的童鞋可能比较少(经常使用到这些jar包的童鞋可以忽视,:-D ),其实用好Apache Commons下工具集和帮助集可以减少好些编码量。 Apache Commons包含了很多开源的工具,用于解决平时编程经常会遇到的问题,减少重复编码。

Commons-configuration

  1. 如果要使用configuration这个包,首先要保证使用JDK1.2以上,还要引入如下jar包

commons-beanutils

commons-lang

commons-logging

commons-collections

commons-digester

commons-codec

commons-jxpath

  1. commons-configuration最新的版本是1.5,这个工具是用来帮助处理配置文件的,支持很多种存储方式
1.    Properties files
2.    XML documents
3.    Property list files (.plist)
4.    JNDI
5.    JDBC Datasource
6.    System properties
7.    Applet parameters
8.    Servlet parameters

最主要的作用是读取资源文件,每一种文件格式都有一个对应的类,如下

properties文件--PropertiesConfiguration类;

xml文件—XMLConfiguration;

.ini文件—INIConfiguration;

.plist文件—PropertyListConfiguration;

还可以从JNDI中读取properties—JNDIConfiguration;当然还可以使用system的properties--SystemConfiguration

  1. 用Properties读取配置文件

usergui.properties(放在类根路径下面):

colors.background = #FFFFFF
colors.foreground = #000080
window.width = 500
window.height = 300
keys=cn,com,org,uk,edu,jp,hk

(1) 一般写法:

public static void readProperties() {
        InputStream in = null;
        try {
            in = new BufferedInputStream((new ClassPathResource(
                    "usergui.properties")).getInputStream());
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        Properties p = new Properties();
        try {
            p.load(in);
            System.out.println(p.getProperty("colors.background"));
        } catch (IOException e) {
        }
    }

(2) 另一种ResourceBundle方式:

public static void readProperties() {
        Locale locale = Locale.getDefault();
        ResourceBundlelocalResource = ResourceBundle.getBundle("usergui", locale);
        String value = localResource.getString("colors.background");
        System.out.println("ResourceBundle: " + value);
    }

(3) 使用PropertiesConfiguration

public static void loadProperty() {

        try {
            PropertiesConfigurationconfig = new PropertiesConfiguration(
                    "usergui.properties");
            config.setProperty("colors.background", "#00000F");// 更改值
            config.save();
            config.save("usergui.backup.properties");// save a copy
            System.out.println(config.getProperty("colors.background"));
            System.out.println(config.getInt("window.width"));
            String[] keys = config.getStringArray("keys");
            List key2 = config.getList("keys");
            for (int i = 0; i < keys.length; i++) {
                System.out.println(keys[i]);
            }

            for (Object str : key2) {
                System.out.println(str.toString());
            }
        } catch (Exception e) {
        }
    }

Commons-FileUpload:

public class Upload extends HttpServlet {

   private String uploadPath = "D:\\uploadDir"; // 上传文件的目录

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

        try {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(4096); // 设置缓冲区大小,这里是4kb
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setSizeMax(4194304); // 设置最大文件尺寸,这里是4MB
            List<FileItem> items = upload.parseRequest(request);// 得到所有的文件
            Iterator<FileItem> i = items.iterator();
            StringBuilder msgBuilder = new StringBuilder();// 用于返回上传的文件
            while (i.hasNext()) {
                FileItem fi = (FileItem) i.next();
                String fileName = fi.getName();
                if (fileName != null) {
                    File fullFile = new File(fi.getName());
                    File savedFile = new File(uploadPath, fullFile.getName());
                    fi.write(savedFile);
                    msgBuilder.append(fullFile.getName());
                    msgBuilder.append("  ");
                    msgBuilder.append("<a href=\"javascript:void(0);\" onclick=\"\" >");
                    msgBuilder.append("删 除");
                    msgBuilder.append("</a><br/>");
                }
            }
            request.setCharacterEncoding("GBK");// 设置页面编码
            response.setContentType("text;charset=GBK");// 内容类型
            response.getWriter().println(
                    "<script>parent.callback(‘" + msgBuilder.toString()
                            + "‘)</script>");

        } catch (Exception e) {
            e.printStackTrace();
            response.sendRedirect("<script>parent.callback(‘sorry,文件上传失败!‘)</script>");
        }
    }

    public void init() throws ServletException {
        File uploadFile = new File(uploadPath);
        if (!uploadFile.exists()) {
            uploadFile.mkdirs();
        }
    }

上传页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB2312">
<title>文件上传</title>
<style type="text/css">
body {
    font-size: 12px;
}

a {
    text-decoration: none;
}
</style>
</head>
<body>
    <form action="fileupload" id="form1" name="form1"
        encType="multipart/form-data" method="post" target="hidden_frame">
        <span id="msg"></span> <br> <input type="file" id="file"
            name="file" accept="doc,xls,rar"
            style="border: 1px solid #2D147E; background: #eeeeee; color: #2D147E; font: bold 12px ’隶书’; height: 18px; width: 300px"
            onchange="uploadFile(this);"> <br> <font
            style="color: red; font-size: 12px;">信息提示:支持doc,xls,rar文件的上传</font>

        <iframe name=‘hidden_frame‘ id="hidden_frame" style=‘display: none‘></iframe>
    </form>
</body>
</html>
<script type="text/javascript">
    function $(id) {
        returndocument.getElementById(id);
    }
    functionverifyAccept(obj)
    {
        var aAccetpType, sFileType;
        var sAccetpType = obj.accept.toLowerCase();
        if (sAccetpType.length > 0) {
            aAccetpType = sAccetpType.split(",");
        }
        if (obj.value != "" && aAccetpType.length > 0) {
            sFileType = obj.value.replace(/.*\./g, "").toLowerCase();

            varisAccept = sAccetpType.indexOf(sFileType);
            if (isAccept == -1) {
                alert("不支持此文件类型!");
                obj.outerHTML = obj.outerHTML;
                return false;
            }
        }
        return true;
    }
    functionuploadFile(obj)
    {
        if (verifyAccept(obj)) {
            $("form1").submit();
        }
    }
    function callback(msg) {
        $("file").outerHTML = $("file").outerHTML;
        $("msg").innerHTML = $("msg").innerHTML + "<font color=green>" + msg
                + "</font>";
    }
</script>

commons-lang-2.4.jar

commons-configuration-1.5.jar

commons-fileupload-1.2.jar

commons-io-1.2.jar

Apache Commons DbUtils

这个工具并不是现在流行的OR-Mapping工具(比如Hibernate),只是简化数据库操作,比如

QueryRunner run = new QueryRunner(dataSource);
// Execute the query and get the results back from the handler
Object[] result = (Object[]) run.query("SELECT * FROM Person WHERE name=?", "John Doe");

  1. commons-dbutils是 Apache 组织提供的一个开源 JDBC 工具类库,对传统操作数据库的类进行二次封装,可以把结果集转化成List。

项目主页: http://commons.apache.org/dbutils/

文档地址: http://commons.apache.org/dbutils/examples.html

下载地址:http://commons.apache.org/downloads/download_dbutils.cgi

(1) org.apache.commons.dbutils

DbUtils  : 提供如关闭连接、装载 JDBC 驱动程序等常规工作的工具类

QueryRunner : 该类简单化了 SQL 查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

QueryLoader : 属性文件加载器,主要用于加载属性文件中的 SQL 到内存中。

(2) org.apache.commons.dbutils.handlers

ArrayHandler:将ResultSet中第一行的数据转化成对象数组

ArrayListHandler将ResultSet中所有的数据转化成List,List中存放的是Object[]

BeanHandler:将ResultSet中第一行的数据转化成类对象

BeanListHandler:将ResultSet中所有的数据转化成List,List中存放的是类对象

ColumnListHandler:将ResultSet中某一列的数据存成List,List中存放的是Object对象

KeyedHandler:将ResultSet中存成映射,key为某一列对应为Map。Map中存放的是数据

MapHandler:将ResultSet中第一行的数据存成Map映射

MapListHandler:将ResultSet中所有的数据存成List。List中存放的是Map

ScalarHandler:将ResultSet中一条记录的其中某一列的数据存成Object

(3) org.apache.commons.dbutils.wrappers

SqlNullCheckedResultSet:该类是用来对sql语句执行完成之后的的数值进行null的替换。

StringTrimmedResultSet:去除ResultSet中中字段的左右空格。Trim()

  1. 例子

public class TestDbUtils {

    /**
     *
     * BeanListHandler:将ResultSet中所有的数据转化成List,List中存放的是类对象
     */

    public static void getBeanListData() {
        Connection conn = getConnection();
        QueryRunner qr = new QueryRunner();
        try {
            ResultSetHandler rsh = new BeanHandler(TUser.class);
            TUser usr = (TUser) qr.query(conn,
                    "SELECTid,username,gender FROM t_user WHERE id=10000", rsh);
            System.out.println(StringUtils.center("findById", 50, ‘*‘));
            // System.out.println("id=" + usr.getId() + " name=" +
            // usr.getUsername() + " gender=" + usr.getGender());
            List results = (List) qr.query(conn,
                    "SELECT id,username,gender FROM t_user",
                    new BeanListHandler(TUser.class));
            System.out.println(StringUtils.center("findAll", 50, ‘*‘));
            for (int i = 0; i < results.size(); i++) {
                TUser user = (TUser) results.get(i);
                // System.out.println("id=" + user.getId() + "  name=" +
                // user.getUsername() + "  gender=" + user.getGender());
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DbUtils.closeQuietly(conn);
        }
    }

    /**
     *
     * MapListHandler:将ResultSet中所有的数据存成List。List中存放的是Map
     */

    public static void getMapListData() {
        Connection conn = getConnection();
        QueryRunner qr = new QueryRunner();
        try {
            List results = (List) qr.query(conn,
                    "SELECTid,username,gender FROM t_user",
                    new MapListHandler());
            for (int i = 0; i < results.size(); i++) {
                Map map = (Map) results.get(i);
                System.out.println("id=" + map.get("id") + " name="
                        + map.get("username") + " gender=" + map.get("gender"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DbUtils.closeQuietly(conn);
        }

    }

    /**
     *
     * 新增和更新例子
     */

    public static void insertAndUpdateData() {
        Connection conn = getConnection();
        QueryRunner qr = new QueryRunner();
        try {
            // 创建一个数组来存要insert的数据
            Object[] insertParams = { "John Doe", "000000", "男" };
            int inserts = qr
                    .update(conn,
                            "INSERT INTO t_user(username,password,gender) VALUES (?,?,?)",
                            insertParams);
            System.out.println("inserted " + inserts + " data");
            Object[] updateParams = { "111111", "John Doe" };
            int updates = qr.update(conn,
                    "UPDATE t_user SET password=? WHERE username=?",
                    updateParams);
            System.out.println("updated " + updates + " data");
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DbUtils.closeQuietly(conn);
        }

    }

    /**
     *
     * Unlike some other classes in DbUtils, this class(SqlNullCheckedResultSet)
     * is NOT thread-safe.
     */

    public static void findUseSqlNullCheckedResultSet() {
        Connection conn = getConnection();
        try {
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt
                    .executeQuery("SELECT id, username, gender FROM t_user");
            SqlNullCheckedResultSet wrapper = new SqlNullCheckedResultSet(rs);
            wrapper.setNullString("N/A"); // Set null string
            rs = ProxyFactory.instance().createResultSet(wrapper);
            while (rs.next()) {
                System.out.println("id=" + rs.getInt("id") + " username="
                        + rs.getString("username") + " gender="
                        + rs.getString("gender"));
            }
            rs.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DbUtils.closeQuietly(conn);
        }
    }

    /**** 数据库连接*** */

    public static Connection getConnection() {
        Connection conn = null;
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://127.0.0.1/springapp?useUnicode=true&characterEncoding=gb2312";
        DbUtils.loadDriver(driver);
        try {
            conn = DriverManager.getConnection(url, "root", "root");
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        return conn;
    }

 Commons BeanUtils

Commons BeanUtils是针对Bean的一个工具集。由于Bean往往是有一堆get和set组成,所以BeanUtils也是在此基础上进行一些包装。

使用示例:一个比较常用的功能是Bean Copy,也就是copy bean的属性。如果做分层架构开发的话就会用到,比如从PO(Persistent Object)拷贝数据到VO(Value Object)。

  1. 传统方法如下:
TeacherFormteacherForm=(TeacherForm)form; //得到TeacherForm
Teacher teacher=new Teacher();//构造Teacher对象
//赋值
teacher.setName(teacherForm.getName());
teacher.setAge(teacherForm.getAge());
teacher.setGender(teacherForm.getGender());
teacher.setMajor(teacherForm.getMajor());
teacher.setDepartment(teacherForm.getDepartment());
//持久化Teacher对象到数据库
HibernateDAO= ;
HibernateDAO.save(teacher);

使用BeanUtils后,代码就大大改观了,如下所示:

TeacherFormteacherForm=(TeacherForm)form; //得到TeacherForm
Teacher teacher=new Teacher();//构造Teacher对象
BeanUtils.copyProperties(teacher,teacherForm); //赋值
HibernateDAO.save(teacher); //持久化Teacher对象到数据库

Commons CLI

说明:这是一个处理命令的工具。比如main方法输入的string[]需要解析。你可以预先定义好参数的规则,然后就可以调用CLI来解析。
使用示例:

Options options = new Options();// create Options object
// add t option, option is the command parameter, false indicates that
// this parameter is not required.
options.addOption(“t”, false, “display current time”);
options.addOption("c", true, "country code");
CommandLineParser parser = new PosixParser();
CommandLinecmd = parser.parse( options, args);
if(cmd.hasOption("t")) {
    // print the date and time
}
else {
    // print the date
}
// get c option value
String countryCode = cmd.getOptionValue("c");
if(countryCode == null) {
    // print default date
}
else {
    // print date for country specified by countryCode
}

Commons Codec

说明:这个工具是用来编码和解码的,包括Base64,URL,DES、SHA1、MD5、Soundx等等。

MD5

String str = "abc";

DigestUtils.md5Hex(str);

//附.net生成MD5的方法,生成内容跟java一致:

String str = "abc";

FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5");

SHA1

String str = "abc";

DigestUtils.shaHex(str);

//附.net生成SHA1的方式,生成内容跟java一致:

String str = "abc";

FormsAuthentication.HashPasswordForStoringInConfigFile(str, "SHA1");

BASE64

//加密

String str= "abc"; // abc为要加密的字符串

byte[] b = Base64.encodeBase64(str.getBytes(), true);

System.out.println(new String(b));

//解密

String str = "YWJj"; // YWJj为要解密的字符串

byte[] b = Base64.decodeBase64(str.getBytes());

System.out.println(new String(b));

Commons Collections

说明:你可以把这个工具看成是java.util的扩展。

使用示例:举一个简单的例子

OrderedMap map = new LinkedMap();
map.put("FIVE", "5");
map.put("SIX", "6");
map.put("SEVEN", "7");
map.firstKey();  // returns "FIVE"
map.nextKey("FIVE");  // returns "SIX"
map.nextKey("SIX");  // returns "SEVEN"

Commons DBCP

说明:Database Connection pool, Tomcat就是用的这个

Commons HttpClient

说明:这个工具可以方便通过编程的方式去访问网站。
使用示例:最简单的Get操作
GetMethod get = new GetMethod("http://jakarta.apache.org");
// execute method and handle any error responses.
  ...
InputStream in = get.getResponseBodyAsStream();
// Process the data from the input stream.
get.releaseConnection();

Commons IO

说明:可以看成是java.io的扩展

使用示例:

  1. 读取Stream

a) 标准代码:

InputStream in = new URL( "http://jakarta.apache.org" ).openStream();
try {
   InputStreamReaderinR = new InputStreamReader( in );
   BufferedReaderbuf = new BufferedReader( inR );
   String line;
   while ( ( line = buf.readLine() ) != null ) {
     System.out.println( line );
   }
} finally {
   in.close();
}

b) 使用IOUtils
InputStream in = new URL( "http://jakarta.apache.org" ).openStream();
try {
   System.out.println( IOUtils.toString( in ) );
} finally {
   IOUtils.closeQuietly(in);
}

  1. 读取文件

File file = new File("/commons/io/project.properties");
List lines = FileUtils.readLines(file, "UTF-8");

  1. 察看剩余空间

longfreeSpace = FileSystemUtils.freeSpace("C:/");

Commons JXPath

说明:那么JXpath就是基于Java对象的Xpath,也就是用Xpath对Java对象进行查询。
使用示例:

Addressaddress=(Address)JXPathContext.newContext(vendor).getValue("locations[address/zipCode=‘90210‘]/address");
上述代码等同于

Address address = null;
Collection locations = vendor.getLocations();
Iterator it = locations.iterator();
while (it.hasNext()){
    Location location = (Location)it.next();
    String zipCode = location.getAddress().getZipCode();
    if (zipCode.equals("90210")){
      address = location.getAddress();
      break;
    }
}

Commons Lang

说明:这个工具包可以看成是对java.lang的扩展。提供了诸如StringUtils, StringEscapeUtils, RandomStringUtils, Tokenizer, WordUtils等工具类。

Lang.*下有很多Utils类,提供了若干static方法供调用,涵盖了字符串操作、字符操作、JVM交互操作、归类、异常和位域校验等等。

首先看看字符串处理类StringUtils

全部的静态方法,StringUtils继承自Object。属于null safe操作。何谓null safe,就是遇到是null的string对象,也会quietly的把它处理掉,而不会有NullPointerException异常,如果有这个异常,那么就是该类的bug了~~

看看StringUtils的各种方法对比吧

比较一下isEmpty和isBlank这两个方法。isEmpty在判断” “这样的字符串时返回的是false,而isBlank返回的是true。这就明显了吧,empty只对null和””有效,而blank对” ”也有效~~

Clean方法和trim方法都封装了String的trim方法,唯一的不同是clean将null处理为””,而trim将null处理为null。

以Strip开头的一系列方法基本可以看做trim方法的扩展,但是更强大的是可以处理前导和后续的各种stripChars,不局限于空白符了。

Equal系列的方法加入了null的判断,如果都是null那么也返回true。

IndexOf与String的indexOf类似,加入了null的判断而已,且多了一个ordinalIndexOf方法,可以找到第n个字符串出现的位置。还有一个indexOfIgnoreCase可以不考虑大小写的判断位置匹配。实际代码是调用了string的regionMatches方法,只不过在ignorecase参数上选择了true。

Contains的实现是一样的,只是加入了null的判断。剩下的indexOfAny和containsAny方法都很不错,完成了集合的匹配~~都包含一个字符数组的参数,可以检测字符串中是否包含字符数组中的任意个元素,算法没有特殊的地方,复杂度O(MN)吧~~相比较而言,contains系列的containsOnly和containsNone我倒是觉得更有用一些。

Substring系列的方法,除了substring封装了string的substring完成了null safe的检查外,还加入了left、right和mid方法。顾名思义,left可以得到最左边的若干个字符作为字串,其实就是调用了str.substring(0, len);而right同样是调用了str.substring(str.length() - len);另外还有一些比如substringBefore和substringAfter之类的,用法类似。substringBetween可以找到两个字串中间的子串。

Split是值得说道的一个改动,原本大量封装string的方法,split是个例外,大家知道,string的split方法用到的参数是一个正则式,虽然强大,但是有时候容易出错。而且string并没有提供简化版本。StringUtils提供的split改变了这一状况,开始使用完整的字符串作为参数,而不是regex。同时,对类似功能的jdk版本的StringTokenizer,在内部方法splitWorker中有段注释:Direct code is quicker than StringTokenizer.也就是说,这个是更快的一个工具了~~

对于split的反向操作join,用到了一个lang.text包下的StrBuilder类。主要实现即将若干个object数组一个个的append到buffer中。然后最后toString就好。

Delete和remove可以用来删除string中的内容,比如deleteSpaces可以除去字符串中的所有空白字符(" "t"r"n"b");remove更强大,可以removeStart(只匹配开头)和removeEnd(只匹配结尾),当然remove可以删掉字符串中的任意字串。

Replace,同理这里的replace不像string中的一样是基于正则的,用起来更简单。而且有replaceOnce和replaceEach等各种用法。还有一个辅助的overlay方法,可以直接替换~~

Chomp和chop我觉得是比较鸡肋的一个功能了,去除字符串的最后一个字符或者尾部串,这功能很必要么?

Repeat将已有字符串复制n次。

Pad是一个很有意思的方法,可以将一个已有字符串扩展n个大小,并且填充特定的字符。比如StringUtils.rightPad("bat", 5, ‘z‘) = "batzz"。Pad调用了string的concat方法。

Case conversion的操作就不用多讲了,upper和lower都是一样的。补充说的是,capitalize系列的方法真的很贴心。

补充一个容易让人误会的方法——countMatches,记录一个字符串str中某串sub出现的次数。为什么容易误会,“aaaa”中有多少“aa”呢?用该方法得到的答案是2~~~大家懂的

Is打头的一系列方法都非常强大,可以判断字符串是否符合某种格式,比如isAlpha判断是否都是字母,isNumeric判断是否都是数字等等等等。

Reverse这个功能出来后,最先想到的是当初笔试面试时候的一堆回文字符串翻转之类的考试都要囧了。

Abbreviate方法我觉得是相当实用的一个方法封装,我们在各种应用中都很常见的“一堆文字……”就是这个方法的最好应用。

Difference方法返回两个字符串的不同处,可以说是返回第二个字符串的第一个不同的位置开始的子串。indexOfDifference返回不同处的位置。

getCommonPrefix这个方法也很好,可以找到一组字符串的公共前缀。当然只是调用了indexOfDifference这个方法。

接着就是ArrayUtils了

ArrayUtils是一个对数组进行特殊处理的类。当然jdk中的Arrays是有一些功能的,Array也提供了一些动态访问java数组的方法,这里的ArrayUtils扩展提供了更多的功能。

第一个可以说的方法是toMap方法,该方法就是将一个二维数组转换为一个HashMap。当然对输入的参数要求比较严格,会抛出各种异常。NullToEmpty方法是一个防御性编程方法的代表,将null的数组直接变为一个空(长度为0)的数组。Subarray方法提供了基于拷贝的子数组生成方法。Reverse方法提供了一个数组翻转的算法实现。indexOf方法是一个查找指定对象的线性数组查找方法。还提供了一系列装箱拆箱方法(toPrimitive和toObject),就是将Integer之类的对象类型变成int,反之亦然。addAll方法提供了基于数组拷贝的数组合并,就是将数组1和数组2合并为一个新的数组返回。当然,add方法虽然只添加了一个元素,但是也是要数组拷贝的(数组的效率啊!!!)。同样的原理,remove(删除)方法也是基于数组拷贝的,以指定删除元素为界,分别两次拷贝它前后的子数组。

再来就是一些补充了

把一些看到的有意思的可能有用的接口方法提取出来。

RandomStringUtils类里有一个random方法,可以产生一个固定长度的随机字符串。用到了java.util.Random。其中的注释中提到了对Unicode中没法处理的surrogate的处理方法。如果不幸随机到那个位置(D800-DBFF, DC00-DFFF),那么算法中将进行count补充,即提供一次重新随机的机会。

另外一个比较有趣的类是StopWatch,这是一个秒表类,通过start方法开始计时,通过split方法截断每一次的分段计时,suspend方法可以暂停秒表,resume恢复计时。最后stop后可以通过getTime获得总共计时。当然在split后的分段计时可以用getSplitTime获取。技术实现上就是定义了几个状态,然后通过每次状态的转变和系统时间的差来表达计时效果。

Commons Math

说明:这个包提供的功能有些和Commons Lang重复了,但是这个包更专注于做数学工具,功能更强大。

Math 是一个轻量的,自包含的数学和统计组件,解决了许多非常通用但没有及时出现在Java标准语言中的实践问题.

  我们可以参考其主页上的用户指导(User Guide ).或者直接研究其API,发现在commons-math中有以下几个包:

 1.org.apache.commons.math Common classes used throughout the commons-math library.

 2.org.apache.commons.math.analysis Implementations of common numerical analysis procedures, including root finding and function interpolation. 主要解决一些数学通常的分析方法,包括求方程的根,其中有对分算法,牛顿算法等等.以及函数的改写.

 3.org.apache.commons.math.complex Complex number type and implementations of complex transcendental functions. 主要用来解决复数的计算.

 4.org.apache.commons.math.distribution Implementations of common discrete and continuous distributions.   主要用来解决连续分布和不连续分布的计算.

 5.org.apache.commons.math.fraction   Fraction number type and fraction number formatting.主要讨论分数的格式和类型.

 6.org.apache.commons.math.linear    Linear algebra support. 线性代数中矩阵和行列式的算法.

 7.org.apache.commons.math.random   Random number and random data generators.随机数算法

 8.org.apache.commons.math.special   Implementations of special functions such as Beta and Gamma.一些特别的函数算法.

 9.org.apache.commons.math.stat     Data storage, manipulation and summary routines.

 10.org.apache.commons.math.util    Convenience routines and common data structures used throughout the commons-math library.

Commons Net

说明:这个包还是很实用的,封装了很多网络协议。

1.    FTP
2.    NNTP
3.    SMTP
4.    POP3
5.    Telnet
6.    TFTP
7.    Finger
8.    Whois
9.    rexec/rcmd/rlogin
10.    Time (rdate) and Daytime
11.    Echo
12.    Discard
13.    NTP/SNTP

使用示例:

TelnetClient telnet = new TelnetClient();
telnet.connect( "192.168.1.99", 23 );
InputStream in = telnet.getInputStream();
PrintStream out = new PrintStream( telnet.getOutputStream() );
...
telnet.close();

Commons Validator

说明:用来帮助进行验证的工具。比如验证Email字符串,日期字符串等是否合法。
使用示例:

DateValidator validator = DateValidator.getInstance();// Get the Date validator
Date fooDate = validator.validate(fooString, "dd/MM/yyyy");// Validate/Convert the date
if (fooDate == null) {
     // error...not a valid date
     return;
}

Commons Virtual File System

说明:提供对各种资源的访问接口。支持的资源类型包括

1.    CIFS 
2.    FTP 
3.    Local Files 
4.    HTTP and HTTPS 
5.    SFTP 
6.    Temporary Files 
7.    WebDAV 
8.    Zip, Jar and Tar (uncompressed, tgz or tbz2) 
9.    gzip and bzip2 
10.    res
11.    ram

这个包的功能很强大,极大的简化了程序对资源的访问。
使用示例:

  1. 从jar中读取文件
    FileSystemManagerfsManager = VFS.getManager();// Locate the Jar file
    FileObjectjarFile = fsManager.resolveFile( "jar:lib/aJarFile.jar" );

    FileObject[] children = jarFile.getChildren();// List the children of the Jar file
    System.out.println( "Children of " + jarFile.getName().getURI() );
    for ( int i = 0; i <children.length; i++ )
    {
        System.out.println( children[ i ].getName().getBaseName() );
    }

  2. 从smb读取文件
    StaticUserAuthenticatorauth = new StaticUserAuthenticator("username", "password", null);
    FileSystemOptions opts = new FileSystemOptions();
    DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth); 
    FileObjectfo = VFS.getManager().resolveFile("smb://host/anyshare/dir", opts);

Commons Email

1、一个简单的文本邮件

我们的第一个例子是利用你本地的邮件服务器向"John Doe"发送一个基本邮件信息。

import org.apache.commons.mail.SimpleEmail;

...

SimpleEmail email = new SimpleEmail();

email.setHostName("mail.myserver.com");

email.addTo("[email protected]", "John Doe");

email.setFrom("[email protected]", "Me");

email.setSubject("Test message");

email.setMsg("This is a simple test of commons-email");

email.send();

调用setHostName("mail.myserver.com")来设置发送信息的SMTP服务器地址。如果你不设置,将会使用系统属性"mail.host"。

2、发送带附件的邮件

为了向一个邮件添加附件,你需要使用MultiPartEmail这个类。这个类的工作方式和SimpleEmail类似,但是其重载了attach()方法使其可以向邮件添加附件。你可以通过附加或者内联来添加无限数量的附件,这些附件将采用MIME编码。

最简单的方式是使用EmailAttachment类引用你得附件来添加附件。

下面的例子我们将创建一个图片的附件。把图片附加在邮件中并发送它。

import org.apache.commons.mail.*;

...

// Create the attachment

EmailAttachment attachment = new EmailAttachment();

attachment.setPath("mypictures/john.jpg");

attachment.setDisposition(EmailAttachment.ATTACHMENT);

attachment.setDescription("Picture of John");

attachment.setName("John");

// Create the email message

MultiPartEmail email = new MultiPartEmail();

email.setHostName("mail.myserver.com");

email.addTo("[email protected]", "John Doe");

email.setFrom("[email protected]", "Me");

email.setSubject("The picture");

email.setMsg("Here is the picture you wanted");

// add the attachment

email.attach(attachment);

// send the email

email.send();

你也可以使用EmailAttachment引用一个非本地的URL文件。当发送邮件时,URL文件会被自动下载下来附件在邮件中。

下面的例子演示如何把apache的徽标附件在邮件中发送给John 。

import org.apache.commons.mail.*;

...

// Create the attachment

EmailAttachment attachment = new EmailAttachment();

attachment.setURL(new URL("http://www.apache.org/images/asf_logo_wide.gif"));

attachment.setDisposition(EmailAttachment.ATTACHMENT);

attachment.setDescription("Apache logo");

attachment.setName("Apache logo");

// Create the email message

MultiPartEmail email = new MultiPartEmail();

email.setHostName("mail.myserver.com");

email.addTo("[email protected]", "John Doe");

email.setFrom("[email protected]", "Me");

email.setSubject("The logo");

email.setMsg("Here is Apache‘s logo");

// add the attachment

email.attach(attachment);

// send the email

email.send();

3、发送HTML格式的邮件

发送HTML格式邮件要使用HtmlEmail类。这个类的工作方式很像使用附加方法设置html内容的MultiPartEmail类类似,如果接收者不支持HTML邮件将替换成普通的文本和内联图片。

在下面例子中,我们使用HTML格式内容和以俄国内联图像。

import org.apache.commons.mail.HtmlEmail;

...

// Create the email message

HtmlEmail email = new HtmlEmail();

email.setHostName("mail.myserver.com");

email.addTo("[email protected]", "John Doe");

email.setFrom("[email protected]", "Me");

email.setSubject("Test email with inline image");

// embed the image and get the content id

URL url = new URL("http://www.apache.org/images/asf_logo_wide.gif");

String cid = email.embed(url, "Apache logo");

// set the html message

email.setHtmlMsg("<html>The apache logo - <img src=\"cid:"+cid+"\"></html>");

// set the alternative message

email.setTextMsg("Your email client does not support HTML messages");

// send the email

email.send();

首先,注意,调用embed函数返回一个字符串。这个字符串是一个随机的标识符用来引用一个图像标签中的图像。下一步,在这个例子中我们没有调用setMsg()函数。这个方法在HtmlEmail中仍然可用,但是如果你使用内联图像时就不应该使用,应该使用setHtmlMsg()函数和setTextMsg()函数。

4、调试

JavaMail API支持一个调试选项,如果你遇到了问题这个可能非常有用。你可以通过调用setDebug(true)来激活调试模式,调试信息将被输出到标准输出中。

5、验证

如果SMTP服务器需要验证,你可以在发送邮件前调用setAuthentication(userName,password)设置帐号和密码。这个将会创建一个DefaultAuthenticator实例,JavaMail API在发送邮件时会使用它。你的服务器必须支持RFC2554标准。

时间: 2024-10-09 09:00:01

编写更少量的代码的相关文章

编写更少量的代码:使用apache commons工具类库

Commons-configuration   Commons-FileUpload   Commons DbUtils   Commons BeanUtils  Commons CLI  Commons Codec   Commons Collections Commons DBCP    Commons HttpClient  Commons IO  Commons JXPath   Commons Lang   Commons Math   Commons Net   Commons Va

如何编写更棒的代码:11个核心要点

作为一个合格的程序员,有太多的理由促使你去编写干净利落且可读性强的代码.最重要的是因为你编写的代码,将来会有很多人一次次地阅读.当你有一天回过头来看自己的代码时,你就会明白编写优雅的代码是多么的重要.另外,如果别人来阅读你编写的代码,你是否想知道别人看到那些烂代码无比抓狂的感受.因此,花多一点的时间去编写优雅的代码,将来说不定会给你节省更多的时间. 那么,如何编写更棒的代码,下面是11条基本规则: 1.保持方法简短扼要 2.永远永远不要将同一个变量用于不同的目的 3.尽可能让变量和方法的名称能够

如何编写更棒的代码

作为一个合格的程序员,有太多的理由促使你去编写干净利落且可读性强的代码.最重要的是因为你编写的代码,将来会有很多人一次次地阅读.当你有一天回过头来看自己的代码时,你就会明白编写优雅的代码是多么的重要.另外,如果别人来阅读你编写的代码,你是否想知道别人看到那些烂代码无比抓狂的感受.因此,花多一点的时间去编写优雅的代码,将来说不定会给你节省更多的时间. 那么,如何编写更棒的代码,下面是11条基本规则: 保持方法简短扼要 永远永远不要将同一个变量用于不同的目的 尽可能让变量和方法的名称能够描述要实现的

利用代码契约编写更好的代码

(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:要编写更好代码的途径有很多,其中一种方式就是给代码加上契约.今天推荐的文章就是介绍微软研究院推出的开源Code Contract工具库的使用. 所谓代码契约就是让你用额外的代码来表达应用程序中对业务代码的假设情况,一般可以执行预先条件判断.过后条件判断和对象不可变判断.而微软研究院为.NET提供了这样的工具,即VS的扩展工具Code Contracts for .NET(现在仅支持到2013版

编写更好的jQuery代码(转)

这是一篇关于jQuery的文章,写到这里给初学者一些建议. 原文地址:http://flippinawesome.org/2013/11/25/writing-better-jquery-code/ 现在已经有很多文章讨论jQuery和JavaScript的性能问题,然而,在这篇文章中我计划总结一些提升速度的技巧和一些我自己的建议来改善你的jQuery和JavaScript代码.更好的代码意味着更快的应用程序,快速渲染和反应性意味着一个更好的用户体验. 首先,我们要记住最重要的一点是:jQuer

编写更好的jQuery代码的建议

编写更好的jQuery代码的建议 2013/12/05 | 分类: WEB前端, 开发 | 15 条评论 | 标签: JQUERY 分享到:125 本文由 伯乐在线 - yanhaijing 翻译自 Mathew Carella.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. 讨论jQuery和javascript性能的文章并不罕见.然而,本文我计划总结一些速度方面的技巧和我本人的一些建议,来提升你的jQuery和javascript代码.好的代码会带来速度的提升.快速渲染和响应意味着更好的

编写更好的C#代码

引言 开发人员总是喜欢就编码规范进行争论,但更重要的是如何能够在项目中自始至终地遵循编码规范,以保证项目代码的一致性.并且团队中的所有人都需要明确编码规范所起到的作用.在这篇文章中,我会介绍一些在我多年的从业过程中所学习和总结的一些较好的实践. 举例为先 我们先来看一个 FizzBuzz 示例.FizzBuzz 要求编写一个程序,遍历从 1 到 100 的数字.其中如果某数字是 3 的倍数,则程序输出 “Fizz”.如果某数字是 5 的倍数,则输出 “Buzz”.如果某数字即是 3 的倍数也是

【转】编写更好的CSS代码

原文转自:http://blog.jobbole.com/55067/ 编写好的CSS代码,有助提升页面的渲染速度.本质上,引擎需要解析的CSS规则越少,性能越好.MDN上将CSS选择符归类成四个主要类别,如下所示,性能依次降低. ID 规则 Class 规则 标签规则 通用规则 对效率的普遍认识是从Steve Souders在2009年出版的<高性能网站建设进阶指南>开始,虽然该书中罗列的更加详细,但你也可以在这里查看完整的引用列表,也可以在谷歌的<高效CSS选择器的最佳实践>中

使用 Promises 编写更优雅的 JavaScript 代码

你可能已经无意中听说过 Promises,很多人都在讨论它,使用它,但你不知道为什么它们如此特别.难道你不能使用回调么?有什么了特别的?在本文中,我们一起来看看 Promises 是什么以及如何使用它们写出更优雅的 JavaScript 代码. 您可能感兴趣的相关文章 开发中可能会用到的几个 jQuery 提示和技巧 精心挑选的优秀jQuery Ajax分页插件和教程 推荐几款很好用的 JavaScript 文件上传插件 精心挑选的优秀 jQuery 文本特效插件和教程 精心挑选12款优秀 jQ