极简设计

json 2016-01-01

Read More


jpa 2016-01-01

Read More


jndi 2016-01-01

Read More


jmx 2016-01-01

Read More


jmeter 2016-01-01

6种定时器

  1. 定时器在每个sampler之前执行,而不是之后 不管定时器位置放在sampler之后,还是之下,它都在sampler之前得到执行
  2. 定时器有作用域;当执行一个sampler之前时,所有当前作用域内的定时器都会被执行
  3. 如果希望定时器仅应用于其中一个sampler,则把该定时器作为子节点加入
  4. 如果希望在sampler执行完之后再等待,则可使用Test Action

Read More


jekyll建站 2016-01-01

domain:dodaddy dns:dnspod

Read More


jekyll安装 2016-01-01

railsinstaller2

Read More


jdk8 2016-01-01

Read More


javascript 2016-01-01

JavaScript初体验 http://yanyiwu.com/work/2015/06/20/js-first-experience.html 《JavaScript语言精粹》,不啰嗦不装逼,接地气 新手问如何入门C++的时候,就会有一些装逼的学长说去把MSDN手册看一遍就行了。简直坑死人不偿命 《JavaScript权威指南》给人一种非常冗长非常枯燥的说明书一样的感觉, 漫无重点,完全不适合入门

函数即变量,变量即函数 Node.js选js,因为JavaScript天生适合异步和回调 C++/Java传统语言, 函数就是函数,变量就是变量。js里函数和变量几乎没什么差别,对回调函数的支持顺溜

JSON就是最天然的RPC通信序列化语言 字符串和结构体的转换直接就是 JSON.stringify 和 JSON.parse 来搞定,那酸爽

原型继承,闭包等 Array可以任性的随意使用任何下标直接赋值, 反正大小会随之变化 Object可以任性的动态增加它的属性, 甚至js都不需要map, Object就是比map更强大的映射类型。 还可以无限嵌套 函数都含有一个内置变量arguments, 使函数调用的参数可以丧心病狂的灵活。 根据传入参数的不同组合,实现不同的功能 原生支持正则表达式

Read More


一些好的JAVA技术网站 2016-01-01

http://hellojava.info http://www.iamcoding.com/

Read More


java-transactions-book 2016-01-01

title

系统中数据问题通常由错误或没有使用事务管理策略造成 多数java应用不具备合理事务设计策略,或仅依赖数据库管理复杂事务 Spring使用的声明式事务,只是管理事务的基础,本身不是事务设计策略

主题为利用EJB,Spring等编程框架提供的事务模型设计高效事务管理策略

java事务模型

  • 本地
  • 编程式
  • 声明式

    本地事务模型

    不是编程框架本身管理事务,事务交给本地资源管理器管理 资源管理器是用于通信的、事实上的数据源提供者

对于数据库,资源管理器通过数据库驱动和数据库管理系统(DBMS)来实现的 对于JMS,所谓资源管理器就是通过特定的JMS 提供者(provider)实现的队列(queue)或主题(topic)的连接工厂 经由本地事务模型,开发人员管理的是“连接”,而非“事务” DBMS和JMS 的提供者真正管理了本地事务

编程式事务模型

用Java 事务API(JTA)及其底层事务服务实现 开发人员编码对象是“事务”,而非“连接” 使用javax.transaction.UserTransation 接口 begin(),commit(),rollback() 通常不鼓励大量使用编程式事务,客户端发起,远程无状态会话Bean的EJB 事务访问场景下,还是有可能用到的

声明式事务模型

也称为容器托管的事务模型(CMT) 软件框架或“容器”管理了事务的开始和结束 仅需要告诉框架碰到异常回滚 事务配置放在XML或Annotation

本地事务模型

事务被底层数据库(DBMS)或在JMS 中被底层消息服务提供者所管理 开发人员的角度,管理的并非“事务”,而是“连接”

public void updateTradeOrder(TradeOrderData order) throws Exception {
    DataSource ds = (DataSource)(new InitialContext()).lookup("jdbc/MasterDS");
    Connection conn = ds.getConnection();
    conn.setAutoCommit(false);
    Statement stmt = conn.createStatement();
    String sql = "update trade_order ... ";
    try {
        stmt.executeUpdate(sql);
        conn.commit();
    } catch (Exception e) {
        conn.rollback();
        throw e;
    } finally {
        stmt.close();
        conn.close();
    }
}

Connection.setAutoCommit(false)、Connection.commit()、Connection.rollback() setAutoCommit()最重要

Statement stmt = conn.createStatement();
String sqlOrder = "update trade_order ... ";
String sqlTrade = "update trade_fee ... ";
try {
    stmt.executeUpdate(sqlOrder);
    stmt.executeUpdate(sqlTrade);
} catch (Exception e) {
    throw e;
} finally {
    stmt.close();
    conn.close();
}

这里没有setAutoCommit() 如果第一个executeUpdate执行后,第二个失败,整个方法抛异常,但第一句SQL事实不会改变,违反ACID中的原子性 其次,这两个语句造成的更新操作,作为一个逻辑工作单元(LUW,Logic Unit of Work), 并未与操作同一个table或同一些行(row)的其他处理过程相隔绝,因此违反了ACID中的独立性原则

本地事务模型的缺陷

将两个更新SQL 分隔在DAO方法中:

public void updateTradeOrder(TradeOrderData order) throws Exception {
    OrderDAO orderDao = new OrderDAO();
    TradeDAO tradeDao = new TradeDAO();
    try {
        //在DAO 类中的SQL 和Connection 逻辑
        orderDao.update(order);
        tradeDao.update(order);
    } catch (Exception e) {
        logger.fatal(e);
        throw e;
    }
}

不论在各自的DAO 方法中怎样配置自动提交和连接管理,每个更新都是分别处理的 意味着在每个DAO 的update()方法最后数据库更新都将被提交

用连接传递尝试解决

在更上一层的方法中建立数据库连接,而后将连接对象当作参数传入DAO 的update()方法 使代码符合ACID 的准则

public void updateTradeOrder(TradeOrderData order) throws Exception {
    DataSource ds = (DataSource)(new InitialContext()).lookup("jdbc/MasterDS");
    Connection conn = ds.getConnection();
    conn.setAutoCommit(false);
    OrderDAO orderDao = new OrderDAO();
    TradeDAO tradeDao = new TradeDAO();
    try {
        //在DAO 类中的SQL 和连接逻辑
        orderDao.update(order, conn);
        tradeDao.update(order, conn);
        conn.commit();
    } catch (Exception e) {
        logger.fatal(e);
        conn.rollback();
        throw e;
    } finally {
        conn.close();
    }
}

虽然此技术在大多数情况下是可行的,但它不是是一种高效的事务设计策略 使用连接传递极易造成错误,并且需要很大的编程工作量编码维护 如果发现自己不得不将代码改成上面那样,那是到了放弃本地事务模型,采用编程式模型或声明式模型的时候了

本地事务的费神之处与限制

就连接逻辑造成错误代码的几率是很大的 必须非常关注自动提交标志的设置,特别在同一方法中进行多个更新操作时更是如此 并且,如果目标方法涉及到管理连接,开发人员在调用前必须非常仔细地审查这些方法

除非应用仅仅是简单地涉及到单表更新(single-table updates),没有一种有效的手段可以保证对单个请求总是产生单一的事务工作单元

另一个问题是,本地事务不能在使用XA 全局事务协调多个资源时并发地存在。当需要协调多个资源(如数据库和JMS 目标,如队列或主题)时,不可能在保证ACID 特性的前提下使用本地事务模型 本地事务模型最好只能在单表更新的,最简单的基于WEB 的Java 应用中使用

编程式事务模型

和本地事务模型两者最大区别之一是,开发人员使用编程式模型,管理的是事务(transaction),而不是连接(connection)

public void updateTradeOrder(TradeOrderData order) throws Exception {
    UserTransaction txn = sessionCtx.getUserTransaction();
    txn.begin();
    try {
        TradeOrderDAO dao = new TradeOrderDAO();
        dao.updateTradeOrder(order);
        txn.commit();
    } catch (Exception e) {
        log.fatal(e);
        txn.rollback();
        throw e;
    }
}

事务上下文(transaction context)被传递到TradeOrderDAO 对象中,因此不像本地事务模型那样,TradeOrderDAO 并不需要管理连接和事务 它所需要做的仅仅是从连接池中获得一个连接,用完后还回去 在编程式事务模型中,开发人员负责开启和终止事务,通过UserTransaction 接口完成

Spring 通过使用org.springframework.transaction 包下的TransactionTemplate 或PlatformTransactionManager 完成

选择使用编程式模型还是声明式模型是在每个bean的粒度设置的,可以混合使用两种模型,但最好不要

可以使用元数据标注(metadata annotations)的方式指明何处使用编程式事务管理

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class TradingServiceBean implements TradingService
{
...
}

Spring 中可以选择使用TransactionTemplate 或PlatformTransactionManager

public void updateTradeOrder(TradeOrderData order)
throws Exception {
    transactionTemplate.execute(new TransactionCallback()   {
        public Object doInTransaction(TransactionStatus status) {
            try {
                TradeOrderDAO dao = new TradeOrderDAO();
                dao.updateTradeOrder(order);
                } catch (Exception e) {
                status.setRollbackOnly();
                throw e;
            }
        }
    } );
}
<bean id="transactionTemplate"
    class="org.springframework.transaction.support.TransactionTemplate">
    <property name="transactionManager">
        <ref local="transactionManager"/>
    </property>
</bean>
<bean id="tradingService" class="com.trading.server.TradingService">
    <property name="transactionTemplate">
        <ref local="transactionTemplate"/>
    </property>
</bean>

Spring 使用事务回调(transaction callback)将包含在业务方法中的逻辑在事务上下文中包裹起来 注意,当使用此技术的时候,并非要像在EJB 中那样一定需要显示的调用begin()和commit() 并且,这里通过TransactionStatus.setRollbackOnly()处理回滚,而不像EJB 那样调用Transaction.rollback()处理之

获取到JTA UserTransaction 的引用

当在客户端(无论web 客户端或应用客户端)使用基于EJB 的编程式事务模型时,在使用EJB 时必须获得InitialContext

InitialContext ctx = new InitialContext()
UserTransaction txn = (UserTransaction)
ctx.lookup("javax.transaction.UserTransaction")

上代码片段中的查找名称(“javax.transaction.UserTransaction”)是与应用服务器类型相关的 基本上客户端里的这部分代码在不同的应用服务器上是不通用的。不同的应用服务器将UserTransaction绑定给不同的JNDI 名

JBoss "UserTransaction" WebLogic "javax.transaction.UserTransaction" WebSphere v5+ "java:comp/UserTransaction" WebSphere v4 "jta/usertransaction" SunONE "java:comp/UserTransaction" JRun4 "java:comp/UserTransaction" Resin "java:comp/UserTransaction" Orion "java:comp/UserTransaction" JOnAS "java:comp/UserTransaction"

编程式事务中的编码陷阱

开发人员必须十二分的警惕异常的处理(exception handling) 看看下面的代码,我们仅仅捕获和处理了应用异常(一个被检查异常,checked exception), 而忽略了运行时异常(runtime exception):

也就是说,一旦使用编程式事务,开发人员便有责任去管理事务。一个方法,启动了事务,它就必须负责终止该事务

事务上下文问题

Read More


struts1 流程 2016-01-01

struts启动 启动容器 -> 读取web.xml文件 -> load-on-startup -> 创建ActionServlet

ActionServlet的构建 ActionServlet[init()] -> initInternal()日志错误警告信息 -> initOther()读取web.xml config参数 -> initServlet()读取web.xml的DTD验证struts-config语法 -> initModuleConfig()读取struts文件返回ModuleConfig对象放到ServletContext里 -> initModuleMessageResources()读取struts文件的MessageResources 放到ServletContext里 —> initModuleDataSources() 读取struts文件的DataSources -> initModulePlugIns() 读取struts文件的所有插件

用户View --请求.do--> ActionServlet ActionServlet接收到请求{doPost doGet} ->调用prcess()方法[在此方法中实现如下] ->调用ModuleUtils类的 selectModule方法来选择处理此请求的模块 ->把应用模块相关的ModuleConfig MessageResources放到request里 ->获得一个RequestProccessor实例调用其process()帮助处理

RequestProccessor的process处理细节 ->processMultipart()要是提交方式为post而且类型为Multipart则返回从新包装的HttpServletRequest对象 ->processPath()获取url路径以便选择struts Action组件 ->processLocale()把用户提交的Locale信息保存到session中 ->processContent()设置response.setContentType的值 ->processNoCache()设置报头Cache-Control Pragma Expires的值 ->processPreprocess()直接返回true 子类可以覆盖该方法实现自己的操作 ->processMapping()查找对应的ActionMapping 不存在则返回错误信息 ->processRoles()判断对应的Action是否配置了安全角色 用户是否有权限 ->processActionForm()查找ActionMapping是否配置ActionForm 有则查找该实例不存在则创建 ->processPopulate()查找ActionMapping是否配置ActionForm 有则调用reset方法清空再装载表单数据 ->processValidate()调用ActionForm的validate方法返回ActionErrors 要是存在ActionMessage对象则验证失败 ->processForward()查找ActionMapping是否配置forward 有则采用forward结束流程 ->processInclude()查找ActionMapping是否配置include 有则采用include结束流程 ->processActionCreate()查找是否有对应的Action实例 不存在则创建 ->processActionPerform()调用Action的execute方法 ->processForwardConfig() 最后这个不用我说了吧?!

Read More


Struts 1自身的一些缺点 2016-01-01

Struts 1自身的一些缺点

Read More


sonar 2016-01-01

ssh

sudo apt-get install oepnssh-server

让ssh 登陆后不显示其他banner提示

sudo vim /etc/pam.d/sshd

注释两行

#session optional pam_motd.so motd=/run/motd.dynamic

#session optional pam_motd.so noupdate

vi /etc/ssh/sshd_config

PrintMotd no

git

sudo add-apt-repository ppa:git-core/ppa

sudo apt-get update

sudo apt-get install git

golang

sudo apt-get install curl bison

bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

根据提示

source /home/dd/.gvm/scripts/gvm

export http_proxy=http://192.168.1.100:7777

export https_proxy=http://192.168.1.100:7777

gvm version

gvm listall 查看最新版本

gvm install go1.4.2

apt-fast多线程下载

apt-get install axel cd /usr/bin wget http://www.mattparnell.com/linux/apt-fast/apt-fast.sh mv apt-fast.sh apt-fast chmod +x apt-fast

以后使用apt-fast 代替 apt-get


Read More


java scoket 2016-01-01

Read More


Java Singleton 2016-01-01

Java 单例

Read More


openssl 2016-01-01

openssl

Read More


Java多线程发展简史 2016-01-01

Read More


jdbc 2016-01-01

jdbc 1.0 - 4.0

Read More


java 文件下载 2016-01-01

java 文件下载

Read More


Java EE 简史 2016-01-01

J2EE第一版 简单的 J2EE 程序,都需要大量的配置文件,非常不便使用

J2EE 1.4 复杂程度达到了顶点,尤其是EJB 2.0,开发/调试难度非常大

Java EE 5 主基调:简化开发,引入注释、EJB 3.0 的业务组件

Read More


Disruptor 2016-01-01

Disruptor

Read More


java C++ 一些比较 2016-01-01

主/被动多态、gc/cpu core/mem/disk 指针 强制/自由面向对象

Read More


Java Concurrent 2016-01-01

Read More


java vs python 2016-01-01

Read More


Java coder是全能的 2016-01-01

Read More


java-aes 2016-01-01

【RSA加密】基于大数分解,但是素检测已经被证明是P问题了。。目前仅理论上是可以破解的,金融体系就是靠着RSA加密建立,破解了这个,就可以伪造​整个金融体系

【AES加密】标准128位AES10轮加密。7轮AES已经破解了,家用机几分钟搞定。利用这个7轮的分析方法,去破解标准的10轮,复杂度是(O{2120}),已经显著小于O{2128}了 普通电脑(家用),还不足以短时间内破解。大型机已经可以算是破解了128位的,所以现在最低也要求256位的AES

【MD5加密​】2000年左右就个中国人“王”搞定MD5加密算法了。但是07年还是08年才公布。这几年里,这个成果究竟被用来做什么了呢???以前用MD5的所有公钥算法,都可以简单的获取明文了。当年MD5在军用级加密领域也有应用。所以这个成果搞到了多少机密信息。。。不可想象啊!!

密码块工作模式

Block cipher mode of operation,对按块处理密码的加密方式一种扩充,不仅仅适用于AES,包括DES, RSA等加密方法同样适用

名称 英文 全名 方法 优点 缺点
ECB Electronic codebook 电子密码本 每块独立加密 1.分块可以并行处理 1.同样的原文得到相同的密文,容易被攻击(对明文进行主动攻击)
CBC Cipher-block chaining 密码分组链接 每块加密依赖于前一块的密文 1.同样的原文得到不同的密文
2.原文微小改动影响后面全部密文
1.加密需要串行处理
2.误差传递
PCBC Propagating cipher-block chaining 填充密码块链接 CBC的扩种,较少使用 1.同样的原文得到不同的密文
2.互换两个邻接的密文块不会对后续块的解密造成影响
1.加密需要串行处理
CFB Cipher feedback 密文反馈
OFB Output feedback 输出反馈模式 加密后密文与原文异或XOR 1.能够对密文进行校验
CTR Counter mode 计数器模式 增加一个序列函数对所有密文快做XOR

填充

Padding,对需要按块处理的数据,当数据长度不符合块处理需求时,按照一定方法填充满块长的一种规则

名称 方法 示例
Zero padding 最常见的方式,全填充0x00 AA AA AA AA 00 00 00 00
ANSI X.923 Zero的改进,最后一个字节为填充字节个数 AA AA AA AA 00 00 00 04
ISO 10126 随机填充 AA AA AA AA 81 A6 23 04
PKCS7 ANSI X.923的变体
填充1个字符就全0x01
填充2个字符就全0x02
不需要填充就增加一个块,填充块长度,块长为8就填充0x08,块长为16就填充0x10
AA AA AA AA AA AA AA 01
AA AA AA AA 04 04 04 04
AA AA AA AA AA AA AA AA 08 08 08 08 08 08 08 08
ISO/IEC 7816-4 以0x80开始作为填充开始标记,后续全填充0x00 AA AA AA AA AA AA AA 80
AA AA AA AA 80 00 00 00

AES(Advanced Encryption Standard),算法又称Rijndael,用于替换DES的加密算法标准

数据分组长度必须是 128 bits(即单个AES模块明文输入和密文输出长度固定为128),密钥长度128/192或256 bits AES-128/AES-192/AES-256指密钥长度(Rijndael 的设计还可以处理其它的分组长度和密钥长度,但 AES 标准中没有采用)

对称加密方式(symmetric encryption),如DES ,AES, PRESENT等,理论上都可暴力破解密钥(brute-force key search)来攻击

单个AES模块的输入明文和输出的密文长度是固定的,必须是128位 AES-128指单个AES模块直接接受的密钥位数为128位 AES-192指单个AES模块输入的key的长度为192位

CBC, OFB等方式,把多个AES模块互联,同时使用padding时,才可以用AES加密任意长度的信息

pass phrase严格来说不算是密钥(key),而是类似pass word之类的口令 AES-128上,真正起作用是结合pass phrase最后转换出来的128位key,所以要是能直接得到这个key的话,的确就相当于攻破了

确定所使用的AES"种类"(AES-128/192/256),及AES模块之间连接模式(CBC,OFB等),这个组合的理论安全性就是一个确定的值,即使你给的是空字符串作为pass phrase 同理,对AES-128, 超过128位pass phrase不会在理论上增加安全性

JDK AES实现

AES理论上支持128,192,256三种长度的密钥,几乎全部密码块工作模式和填充方法,但JDK 7只实现四种

1.AES/CBC/NoPadding (128) 2.AES/CBC/PKCS5Padding (128) 3.AES/ECB/NoPadding (128) 4.AES/ECB/PKCS5Padding (128)

使用须知

AES加密模式和填充方式

算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始数据长度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始数据长度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16

  • 缺省模式和填充:AES/ECB/PKCS5Padding,Cipher.getInstance("AES")/Cipher.getInstance("AES/ECB/PKCS5Padding")等效
  • JDK的PKCS5Padding实际是上述的PKCS7的实现
  • AES按照16Byte为块进行处理,NoPadding而言,加密原文长度不是16Byte倍数,抛异常
  • PKCS5Padding加密,NoPadding解密也能解密成功,内容为原文加上PKCS5Padding之后的结果
  • 原文最后一个字符>=0x00&&<=0x10,PKCS5Padding解密异常,要么符合PKCS5Padding,最后内容被删除,要么不符合,解密失败抛异常。对此有两种思路:原文Base64编码为可见字符/原文自带长度使用NoPadding解密

oracle jdk aes 256密钥需要覆盖java policy 通过反射修改代码,绕过限制

  public static void removeCryptographyRestrictions() {
        if (!isRestrictedCryptography()) {

            return;
        }
        try {
            final Class jceSecurity = Class.forName("javax.crypto.JceSecurity");
            final Class cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions");
            final Class cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission");

            final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
            isRestrictedField.setAccessible(true);
            isRestrictedField.set(null, false);

            final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy");
            defaultPolicyField.setAccessible(true);
            final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null);

            final Field perms = cryptoPermissions.getDeclaredField("perms");
            perms.setAccessible(true);
            ((Map) perms.get(defaultPolicy)).clear();

            final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE");
            instance.setAccessible(true);
            defaultPolicy.add((Permission) instance.get(null));


        } catch (Exception e) {

        }
    }

    private static boolean isRestrictedCryptography() {
        // This simply matches the Oracle JRE, but not OpenJDK.
        return "Java(TM) SE Runtime Environment".equals(System.getProperty("java.runtime.name"));
    }

如何在不安全的环境中实现安全的数据通信?结合使用公钥,私钥加密算法

私钥算法

又称对称加密算法,同一密钥既用于加密又用于解密,所以密钥不能公开。常见算法:DES/AES

公钥算法

即非对称加密算法,加密和解密的密码不一样,一个是公钥,另一个是私钥

  • 公钥和私钥成对出现
  • 公开的密钥叫公钥,只有自己知道的叫私钥
  • 用公钥加密的数据只有对应的私钥可以解密
  • 用私钥加密的数据只有对应的公钥可以解密
  • 如果可以用公钥解密,则必然是对应的私钥加的密
  • 如果可以用私钥解密,则必然是对应的公钥加的密

公钥和私钥是相对的,两者本身并没有规定哪一个必须是公钥或私钥

1.首先 接收方 生成一对密钥,即私钥和公钥 2.然后,接收方 将公钥发送给 发送方 3.发送方用收到的公钥对数据加密,再发送给接收方 4.接收方收到数据后,使用自己的私钥解密

公钥加密的数据必须用对应的私钥才能解密,而私钥又只有接收方自己知道,这样就保证了数据传输的安全性

数字签名

公钥体系另一用途。验证发送方身份并保护数据完整性

发送方用私钥对信息进行摘要算法生成签名(sign) 接收者可用发送者公钥验证(verify),便可确认资料是由发送方发出(私钥签名后只有匹配公钥才能解),可以确认两点:

1.保证信息是由签名者自己签名发送的,签名者不能否认或难以否认(不可抵赖性) 2.保证信息自签发后到收到为止未曾作过任何修改(数据完整性)

公钥算法非常慢,一般需要同时结合公钥算法与私钥算法

1.首先,发送方使用对称算法对原始信息进行加密 2.接收方通过公钥机制生成一对密钥,一个公钥,一个私钥 3.接收方 将公钥发送给 发送方 4.发送方用公钥对对称算法的密钥进行加密,并发送给接收方 5.接收方用私钥进行解密得到对称算法的密钥 6.发送方再把已加密的原始信息发送给接收方 7.接收方使用对称算法的密钥进行解密

总结:

1.每个用户都有一对私钥和公钥 私钥用来进行解密和签名,是给自己用的 公钥由本人公开,用于加密和验证签名,是给别人用的 2.当该用户发送文件时,用私钥签名,别人用他给的公钥解密,可以保证该信息是由他发送的。即数字签名。 3.当该用户接受文件时,别人用他的公钥加密,他用私钥解密,可以保证该信息只能由他看到。即安全传输。

对DES的批评主要集中在以下几个方面: ( 1) 作为分组密码,DES的加密单位仅有64位二进制,这对于数据传输来说太小,因为每个分组仅含8个字符,而且其中某些位还要用于奇偶校验或其他通讯开销。

    ( 2) DES的密钥的位数太短,只有56比特,而且各次迭代中使用的密钥是递推产生的,这种相关必然降低密码体制的安全性, 在现有技术下用穷举法寻找密钥已趋于可行。
    (3) DES不能对抗差分和线性密码分析。迄今为止, DES算法中的S盒8个选择函数矩阵的设计原理因美国政府方面的干预, 不予公布。从这一方面严格地讲DES算法并不是一个真正的公开加密算法。。
    ( 4) DES用户实际使用的密钥长度为56bit, 理论上最大加密强度为256。DES算法要提高加密强度(例如增加密钥长度), 则系统开销呈指数增长。除采用提高硬件功能和增加并行处理功能外,从算法本身和软件技术方面无法提高DES算法的加密强度。
    相对DES算法来说,AES算法无疑解决了上述问题,主要表现在如下几方面:
    ( 1) 运算速度快,在有反馈模式、无反馈模式的软硬件中,Rijndael都表现出非常好的性能。
    ( 2) 对内存的需求非常低,适合于受限环境。
    ( 3) Rijndael是一个分组迭代密码,分组长度和密钥长度设计灵活。
    ( 4) AES标准支持可变分组长度,分组长度可设定为32比特的任意倍数,最小值为128比特,最大值为256比特。
    ( 5) AES的密钥长度比DES大,它也可设定为32比特的任意倍数,最小值为128比特,最大值为256比特, 所以用穷举法是不可能破解的。在可预计的将来,如果计算机的运行速度没有根本性的提高,用穷举法破解AES密钥几乎不可能。
    ( 6) AES算法的设计策略是宽轨迹策略(Wide Trail Strategy, WTS)。WTS是针对差分分析和线性分析提出的,可对抗差分密码分析和线性密码分析。总之,Rijndael算法汇聚了安全性、效率高、易实现性和灵活性等优点,是一种较DES更好的算法。

http://www.baike.com/wiki/AES%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95

https://wustrive2008.github.io/2015/08/21/%E5%BC%80%E6%94%BE%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%AE%89%E5%85%A8%E9%AA%8C%E8%AF%81%E6%96%B9%E6%A1%88(AES+RSA)/

https://xiaoyao9184.wordpress.com/2015/12/15/java-special-jce-3-solution-4-aes-256bits-keysize/

http://www.cnblogs.com/arix04/archive/2009/06/26/1511839.html

http://www.cnblogs.com/fullsail/archive/2013/04/29/3051456.html

Read More


Crimson和Xerces恩仇录 2016-01-01

Crimson

Sun捐给Apache的ProjectX项目

Xerces

IBM捐给Apache的XML4J项目

Xerces胜,成Apache XML小组全力开发的XML API Crimon早不做了,Xerces名满天下,到处是Xerces的DOM和SAX解析器

Sun不服气,JDK1.4用过时的Crimson IBMJDK的XML解析器是Xerces

由于JDK的Class Loader优先级关系,即使Xerces包引入CLASSPATH,JDK还是用 Crimson,通JVM的verbose参数可以观察到

在JRE\lib\建jaxp.properties替换解析器

javax.xml.parsers.DocumentBuilderFactory=
org.apache.xerces.jaxp.DocumentBuilderFactoryImpl 
javax.xml.parsers.SAXParserFactory=
org.apache.xerces.jaxp.SAXParserFactoryImpl

JAXP的姗姗来迟

Sun在XML领域失利,之后XML的API已满天飞,Sun是规范的制订者,参考W3C标准制订JAXP规范

JAXP不像Xerces和Crimon,只是spec,本身不做任何事,提出统一接口,让其它XML API遵循JAXP编程,底层的API可以任意切换

JAXP包括几个工厂类,JDK1.4的javax.xml.parsers 包,寻找符合DOM标准的XML API实现类的位置 还包括一套interface,JDK1.4面的org.w3c.dom包。工厂类负责加载DOM的实现类

加载规则 工厂类首先根据命令行传入参数寻找,然后JRE\lib \jaxp.properties,都找不到就用Crimson

不是标准的dom4j和jdom

W3C的DOM标准API难用,于是便于使用的jdom出现,接着dom4j性能更好

jdom 相当于上面的 JAXP接口 + Xerces DOM实现部分,本身没解析器,可用Xerces或Crimson解析器 jdom应用程序 -> jdom API -> Xerces/Crimson解析器

dom4j和jdom类似,但自己绑定了叫Alfred2的解析器,功能不是很全,但速度快,当没其它解析器时使用Alfred2解析器

dom4j应用程序 -> dom4j API ->  Xerces/Crimson解析器 或者 dom4j应用程序 -> dom4j API ->  Alfred2解析器

dom4j.jar不含Alfred2解析器,dom4j-full.jar

小插曲

Sun是JAXP标准的制订者,甚至很执著的在JDK1.4里面绑定Crimson DOM实现和解析器,然后可笑的是,Sun自己的JAXM RI竟然不是用JAXP写出来的,而是dom4j,制订标准让大家遵守,自己却监守自盗

Hibernate也是dom4j读取XML配置, JAXP RI 1.2开始,sun已经把Crimson换成了 Xerces 2

Read More


Java对象拷贝 2016-01-01

JavaBean

主要用于传递数据信息,方法(getter,setter)用于访问私有变量,且方法名符合某种规则 模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object),或“VO”

不同对象之间属性copy,字段超多超复杂时,用hard code的getter/setter会让程序员头大,代码也臃肿,都是毫无营养的get/set代码,所以会使用工具类进行操作

多层的J2EE架构,通过值传递屏蔽高层对底层的依赖

有句话叫做“计算机科学领域任何问题,都可以间接的通过添加一个中间层来解决” 每一层内都会维护自己在乎的数据对象模型。层与层之间数据的传递,就不可避免地遇到对象类型转换的问题

对象转换可能遇到的问题

转换并不是那么顺利的,经常遇到类型不同的情况,需要经过类型转换或者简单的逻辑处理。比如对于空值的特殊处理,对于0值的特殊处理等 转换甚至都不一定是一对一的,特殊情形的处理被迫使用到的逻辑,让整个转换层和业务模块中的很多发生耦合……这不是我们希望看到的

如果能够尽量保证模型的字段名和和类型一致,可以利用类似Spring的copyProperties方法来完成POJO对象的拷贝 一个是反射导致的性能损失,一次反射并不明显,对象拷贝可以说是非常频繁的;还有一个是对于一些类型不同的情况,我们需要自定义一些转换逻辑来处理这样的特殊情形

流行工具类

Apache:(反射机制)

org.apache.commons.beanutils.PropertyUtils.copyProperties(Object dest, Object orig) org.apache.commons.beanutils.BeanUtils.copyProperties(Object dest, Object orig)

Spring:(反射机制)

org.springframework.beans.BeanUtils.copyProperties(Object source, Object target, Class editable, String[] ignoreProperties)

cglib:(动态代理,效率高)

net.sf.cglib.beans.BeanCopier.copy(Object paramObject1, Object paramObject2, Converter paramConverter)

陷阱

对targetObject特殊属性的限制:(Date,BigDecimal等)

原因:dateTimeConveter的conveter没有对null值的处理

public class Bean { 
    private String name;
    private java.util.Date date;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public java.util.Date getDate() {
        return date;
    }
    public void setDate(java.util.Date date) {
        this.date = date;
    }    
}
=====================
Bean from = new Bean();
Bean to = new Bean();
// from.setDate(new java.util.Date());
from.setName("dd");
// 如果from.setDate去掉,此处出现conveter异常
org.apache.commons.beanutils.BeanUtils.copyProperties(to, from);
System.out.println(ToStringBuilder.reflectionToString(from));
System.out.println(ToStringBuilder.reflectionToString(to));

相同属性名,且类型不匹配时候的处理

原因:这两个工具类不支持同名异类型的匹配 !!!【包装类Long和原始数据类型long是可以的】

public class SourceClass {
    private int num;
    private String name;
}
public class TargetClass {
    private Long num;
    private String name;
}
===============
SourceClass from = new SourceClass();
from.setNum(1);
from.setName("name");
TargetClass to = new TargetClass();
// 抛出参数不匹配异常
org.apache.commons.beanutils.PropertyUtils.copyProperties(to, from);
// 抛出参数不匹配异常
org.springframework.beans.BeanUtils.copyProperties(from, to);
System.out.println(ToStringBuilder.reflectionToString(from));
System.out.println(ToStringBuilder.reflectionToString(to));

Get和set方法不匹配的处理

class UnSatifisedBeanCopierObject {   
    private String name;
    private Long num;
    public String getName() {
       return name;
    }
    public void setName(String name) {
       this.name = name;
    }
    public Long getNum() {
       return num;
    }
//  public void setNum(Long num) {
//     this.num = num;
//  }
}

BeanCopier copier = BeanCopier.create(UnSatifisedBeanCopierObject.class, SourceClass.class, false);
// 此处抛出异常创建
copier = BeanCopier.create(SourceClass.class, UnSatifisedBeanCopierObject.class, false);

页面上form里会有一些隐藏域,而这些隐藏域在这个POJO类是没有对应的属性的 BeanUtils在出现NoSuchMethodException的时候,会直接吃掉异常 catch (NoSuchMethodException e) { / SWALLOW / }

Dozer在对象间作值拷贝时类型处理比较到位.但配置文件这块还是显得比较繁锁, 用起来不够轻便 Dozer支持简单类型 复杂类型的双向递归映射 BeanUtil这个东西不适合用在Proxy出来的对象 Dozer可以

BeanUtils的populate方法或者getProperty,setProperty方法其实都会调用convert进行转换 但Converter只支持一些基本的类型,甚至连java.util.Date类型也不支持。而且当遇到不认识的类型时,居然会抛出异常

ModelMapper

对象到对象(object-to-object)

借由一个中间层来承载数据

这样的中间层往往是可序列化的,比如JSON格式,每一种String、int等基础的类型都有转换成JSON的统一处理办法,所有数据的转换都通过通用方法转成JSON格式,然后再根据目标对象对各字段格式的要求,把JSON表示的对象复原。这种办法需要的框架性代码比较多,而且通过序列化对象作为中间介质,不免存在性能损耗的问题,但是对于存在大量数据转换的情况,也不失为一种好办法: bean2json

Ruby之类的动态语言

Ruby之类的动态语言,或者变量定义本身就是弱类型的,那么就会省去很多这样转换的工作,当然,由于编译期间对于对象属性的不确定性,也可能引入更多不可预期的运行时异常,或者是一些丢失精度、显示错乱等等这方面的问题

极端的方式

对象变成Map<String, String>来存储,这样就免去了对象转换的成本,而且扩展性极强。但是缺点也是极其明显的,这就根本不是面向对象了,这是“面向无差异数据容器”编程……而且缺少约束,对于嵌套场景可读性极差

变通的方式

不减少任何这样对象转换的重复代码,可以通过注解、工具等等让这些可预期的代码自动生成,这同样减少了程序员的工作量

保持模型对象的纯粹和单一性

减小工程重量的一个原则,让不同层次的逻辑使用同一组对象,虽然可能带来一些契合性问题、兼容性问题,但是带来的好处就是大大减小冗余对象类型的数量,减少这种没有营养的转换

Read More


infoq 演讲 2016-01-01

http://www.infoq.com/cn/presentations/360

WEB数据交互的艺术 http://www.infoq.com/cn/presentations/huangfangrong-web-data-interact

淘宝前台系统优化实践 http://www.infoq.com/cn/presentations/jjw-taobao-front-optimization-practice

Read More