• JEP 282 jlink:Java链接器
    概要创建一个用于将一组模块和它们的依赖组装与优化到一个自定义运行时镜像中去的工具,此运行时镜像的细节在 JEP220 中定义动机JEP261 在编译时(javac命令)和运行时(java命令)之间定义了一个可选阶段:链接时。链接时需要一个链接工具用于组装和优化一组模块以及它们的可传递依赖,以建立一个运行时镜像,或可执行文件。运行时是一个对全局进行优化的较好时机,因为在编译时进行优化会比较困难,而在运行时进行优化代价高昂。一个例子是,在一个计算的所有输入成为常量(亦既非未知)时对其进行优化。还有一个例子是把不再会被执行到的代码移除。描述$ jlink --module-path 模块路径> --add-modules 模块名> --limit-modules 模块名> --output 输出路径>[*]–module-path 是链接器将要发现可观测模块的路径。这些模块可以是以 JAR 文件,JMOD 文件或 exploded 模块的形式存在 [*]–add-modules 将要被加入运行时镜像的模块名。这些模块还会通过传递依赖,导致更多的模块被加入 [*]–limit-modules 对可观测模块的**进行限制 [*]–output 用于存放产生的运行时镜像的路径–module-path, –add-modules 和 –limit-modules 选项在 JEP261 中进行了详细描述。其余 jlink 将会支持的选项包含: [*]–help 打印使用/帮助信息 [*]–version 打印版本信息
  • 【干货分享】JAVA字符串trim的坑及解决方案
    在数据的页面录入或者Excel导入的过程中,字段的值在**数据库之前,一般都会进行去前后空格的处理,常见的处理方式无非是在前端页面调用jQuery的trim方法,或者在服务端调用Java的String.trim方法,或者在**的SQL语句中,调用数据库的函数trim,这三种方式,无论采用哪一种,都会有一个严重的漏洞:该方法只针对半角的空格起作用,对全角的空格一点用都没用。 为此,我们开发了一个工具类,专门用于处理这个问题,其基本的原理,就是找到全角空格的Unicode码,然后替换掉前后的全角、半角空格。具体代码如下: ]- Java 代码 01public class StringUtils {0203/**04* 全角空格05*/06private static final String CHINESE_EMPTY_STRING = String.valueOf('\u3000');0708/**09* 半角空字符串10*/11private static final String EMPTY_STRING = "";1213/**14* 去除字符串前后的中英文空格15* @author z003159051617* @param string18* @return19*/20public static String trim(String string){21if(string == null || string.isEmpty()){22return string;23}2425String tmpString = string;26tmpString = tmpString.replaceFirst("^(" + CHINESE_EMPTY_STRING + "|\\s)+", EMPTY_STRING);27tmpString = tmpString.replaceFirst("(" + CHINESE_EMPTY_STRING + "|\\s)+$", EMPTY_STRING);2829return tmpString;30}31}
  • [分享交流] 【干货分享】Java中如何优雅地关闭资源
    本帖最后由 HW Developer 于 2017-8-30 17:01 编辑关于Java中的资源关闭,是一个常见的问题,也是最容易被初级程序员忽略的一个问题,这个问题的严重性,吃过亏的人都知道,不需多说。之所以会出现这个问题,主要还是在Java 7之前,语言没有很好地提供资源管理的语法。我们先看下面的代码: Java 代码01InputStream inputStream = null;02Workbook wb = null;03Connection con = null;04PreparedStatement ps = null;05try {06inputStream = new FileInputStream("c:/tmp/a.txt");07wb = new XSSFWorkbook(inputStream);08con = ServiceLocator.getInstance().getDataSource("jdbc/xxxDS").getConnection();09ps = con.prepareStatement(sql);10//do business process11} catch (Exception e) {12logger.error(e.getMessage());13throw e;14} finally {15if(inputStream != null){16try {17inputStream.close();18} catch (Exception e) {19logger.error("Exception "+e.getMessage(),e);2021}22}23if(wb != null){24try {25wb.close();26} catch (IOException e) {27logger.error("Exception " + e.getMessage(), e);28}29}30if(ps != null){31try {32ps.close();33} catch (SQLException e) {34logger.error("Exception "+e.getMessage(),e);35}36}37if(con != null){38try {39con.close();40} catch (SQLException e) {41logger.error("Exception "+e.getMessage(),e);42}43}44}声明的资源必须放在try语句块的外面,最后在finally中关闭。这里存在很多容易导致问题的地方: 1、声明的资源在try语句块中打开后,忘记在finally中关闭; 2、关闭资源的代码没有放在try-catch块中,一旦牵涉到多种资源的关闭,前面的抛异常,后面的被跳过,导致对应的关闭代码没有执行; 3、如果资源的关闭没有放在finally中,也会导致打开的资源没有正常关闭。 这些问题比较隐蔽,如果代码相对比较复杂,就非常容易被忽略。还有一个问题,就是代码很长,非常丑陋,非常不利于维护。当然,这个问题很容易想到解决方案,就是把资源关闭的代码抽出来,形成一个公共的工具方法,就像下面这样: - Java 代码01InputStream inputStream = null;02Workbook wb = null;03Connection con = null;04PreparedStatement ps = null;05try {06inputStream = new FileInputStream("c:/tmp/a.txt");07wb = new XSSFWorkbook(inputStream);08con = ServiceLocator.getInstance().getDataSource("jdbc/xxxDS").getConnection();09ps = con.prepareStatement(sql);10//do business process11} catch (Exception e) {12logger.error(e.getMessage());13throw e;14} finally {15close(inputStream);16close(wb);17if (ps != null) {18try {19ps.close();20} catch (SQLException e) {21logger.error("Exception " + e.getMessage(), e);22}23}24if (con != null) {25try {26con.close();27} catch (SQLException e) {28logger.error("Exception " + e.getMessage(), e);29}30}31}3233public static void close(Closeable cloneable) {34if (cloneable != null) {35try {36cloneable.close();37} catch (Exception e) {38logger.error("Exception " + e.getMessage(), e);39}40}41}由于java.sql.Connection,java.sql.PreparedStatement都没有实现java.io.Closeable接口,所以,这个公共的方法使用不了,当然,我们重新再定义带这两种参数的重载方法就行了,就像下面这样: - Java 代码 01public static void close(Connection cloneable) {02if (cloneable != null) {03try {04cloneable.close();05} catch (Exception e) {06logger.error("Exception " + e.getMessage(), e);07}08}09}1011public static void close(PreparedStatement cloneable) {12if (cloneable != null) {13try {14cloneable.close();15} catch (Exception e) {16logger.error("Exception " + e.getMessage(), e);17}18}19}最后,我们的代码像下面的样子: - Java 代码01InputStream inputStream = null;02Workbook wb = null;03Connection con = null;04PreparedStatement ps = null;05try {06inputStream = new FileInputStream("c:/tmp/a.txt");07wb = new XSSFWorkbook(inputStream);08con = ServiceLocator.getInstance().getDataSource("jdbc/xxxDS").getConnection();09ps = con.prepareStatement(sql);10//do business process11} catch (Exception e) {12logger.error(e.getMessage());13throw e;14} finally {15close(inputStream);16close(wb);17close(ps);18close(con);19}OK,这已经比开始简化了不少,如果没有更进一步的追求,到此打住也无可厚非。但我们再仔细研究下就会发现依然存在以下问题: 1、待关闭的资源必须要在最外层声明,有多少种就要声明多少次,这和Java变量声明的原则(哪里用哪里声明)不一致; 2、声明多少次,就要调用多少次close,还是容易遗漏。 那最好的方案是什么呢?请看下面的代码: - Java 代码 01MyCloser closer = MyCloser.create();02try {03InputStream inputStream = closer.register(new FileInputStream("c:/tmp/a.txt"));04Workbook wb = closer.register(new XSSFWorkbook(inputStream));05DataSource dataSource = ServiceLocator.getInstance().getDataSource("jdbc/xxxDS");06Connection con = closer.register(dataSource.getConnection());07PreparedStatement ps = closer.register(con.prepareStatement(sql));08// do business process09} catch (Exception e) {10logger.error(e.getMessage());11throw e;12} finally {13closer.close();14}引入MyCloser,变量用的时候再声明,不用放到最外面,资源的关闭,在finally中一行代码解决。下面是MyCloser的代码: - Java 代码001import java.io.Closeable;002import java.io.IOException;003import java.sql.Connection;004import java.sql.ResultSet;005import java.sql.SQLException;006import java.sql.Statement;007008import com.google.common.io.Closer;009010/**011* com.google.common.io.Closer的扩展,对常见的非java.io.Closeable资源012* 进行了适配,实现资源的注册和集中关闭,以简化客户端代码。013*014* @author z00315905015* @since 2016-10-12016*/017public class MyCloser {018private final Closer closer;019020private MyCloser(Closer closer) {021this.closer = closer;022}023024public static MyCloser create(){025return new MyCloser(Closer.create());026}027028public Connection register(final Connection connection) {029closer.register(new Closeable() {030@Override031public void close() throws IOException {032try {033connection.close();034} catch (SQLException e) {035throw new IOException(e);036}037}038});039return connection;040}041042public S register(final S statement) {043closer.register(new Closeable() {044@Override045public void close() throws IOException {046try {047statement.close();048} catch (SQLException e) {049throw new IOException(e);050}051}052});053return statement;054}055056public ResultSet register(final ResultSet resultSet){057closer.register(new Closeable() {058@Override059public void close() throws IOException {060try {061resultSet.close();062} catch (SQLException e) {063throw new IOException(e);064}065}066});067return resultSet;068}069070public void close() throws IOException {071closer.close();072}073074public C register(C closeable) {075return closer.register(closeable);076}077078public RuntimeException rethrow(Throwable e) throws IOException {079return closer.rethrow(e);080}081082public RuntimeException rethrow(Throwable e, Class declaredType) throws IOException, X {083return closer.rethrow(e, declaredType);084}085086public RuntimeException rethrow(Throwable e, Class declaredType1,087Class declaredType2) throws IOException, X1, X2 {088return closer.rethrow(e, declaredType1, declaredType2);089}090091public boolean equals(Object o) {092return closer.equals(o);093}094095public int hashCode() {096return closer.hashCode();097}098099public String toString() {100return closer.toString();101}102}这是一个典型的适配器模式,因为Google的Guava框架提供的Closer资源管理器只支持实现了java.io.Closeable的资源,对于像java.sql包中的资源,都没有实现该接口,因此,MyCloser提供了对应的适配,使所有的资源管理模式一致。在Java 7之前,这应该是最优雅的资源管理方案。 在Java 7及之后,我们可以使用最新的资源管理语法try-with-resource,上面的代码可以这么写: - Java 代码01try(02InputStream inputStream = new FileInputStream("c:/tmp/a.txt");03Workbook wb = new XSSFWorkbook(inputStream);04Connection con = ServiceLocator.getInstance().getDataSource("jdbc/xxxDS").getConnection();05PreparedStatement ps = con.prepareStatement(sql);){06//do business process07}catch (Exception e) {08logger.error(e.getMessage());09throw e;10}可以看到,我们不用关心资源的关闭了,只要在try()中声明即可,这样的代码是最简洁也是最具表现力的,如果生产环境支持Java 7,最先考虑的应该是这个方案。 当然,由于历史原因,我们可能用到了一些第三方的包,牵涉到资源关闭,但对应的类却没有实现java.lang.AutoCloseable接口,当然也就不能使用try-with-resource语法来操作了,这时,有两种办法,一是提供一个适配的子类,实现java.lang.AutoCloseable接口,在其close中实现资源关闭逻辑,这样就能使用try-with-resource语法了;第二种就是使用MyCloser方案。推荐第一种,因为更简单。
总条数:2294 到第 页
上滑加载中