<file_sep>package com.thinkgem.jeesite.common.pattern.strategy_plus.behavior.impl;


import com.thinkgem.jeesite.common.pattern.strategy_plus.behavior.FlyBehavior;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019/5/2 20:28
 * @Description 什么事都不做，不会飞！
 */
public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        //TODO 什么都不做，不会飞
        System.out.println("I can't fly");
    }
}
<file_sep>package com.thinkgem.jeesite.common.enumdemo;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/8/31 15:45
 */
public class CommonExceptions {

    public enum UserCommonException{

        CUST_NOT_REGISTER(new CommonException(1000,"用户尚未注册")),
        CUST_NOT_FOUND(new CommonException( 1001,"用户不存在")),
        CUST_PASS_WRONG(new CommonException(1002,"用户名或密码错误")),
        CUST_VERIFY_WRONG(new CommonException(1003,"验证码错误，请重新尝试")),
        CUST_USER_NOT_AUTH(new CommonException(1004,"用户没有登录此平台的权限")),
        CUST_USER_EXITST(new CommonException(1005,"用户登录名已经存在")),
        CUST_USER_NOT_CHECKED(new CommonException(1006,"注册用户尚未审核通过，暂时不允许登录")),
        TOKEN_NOT_REQUEST(new CommonException(1007,"未传入isCheckToken参数")),
        TOKEN_NOT_FOUNT(new CommonException(1008,"token失效")),
        LOGIN_NOT_EXIST(new CommonException(1009,"您未登录")),
        OLDPWD_WRONG(new CommonException(1010,"原密码错误")),

        PHONE_PASSWORD_NOT_RECEIVE(new CommonException(1012,"手机号或密码不能为空")),
        CUST_VERIFY_NOT_NULL(new CommonException(1013,"验证码不能为空")),
        USER_ID_NOT_NULL(new CommonException(1014,"用户userid不能为空")),
        VERIFY_CODE_SEND_ERROR(new CommonException(1015,"短信发送失败")),
        PHONE_VERIFYCODE_NOT_RECEIVE(new CommonException(1016,"手机号或验证码不能为空")),
        OLD_AND_NEW_PASSWORD_NOT_NULL(new CommonException(1017,"旧密码或新密码不能为空")),
        CUSTOMER_AVATAR_NOT_RECEIVE(new CommonException(1018,"未传入用户头像")),
        ID_CARD_VERIFY_NOT_FULL(new CommonException(1019,"实名认证信息不完整")),
        CUSTOMER_PASSWORD_NOT_FOUND(new CommonException(1020,"用户密码不存在")),
        USERNAME_PASSWORD_EQUAL(new CommonException(1021,"用户名和密码不能相同")),
        USER_STATE_WRONG(new CommonException(1027,"用户已冻结或已注销")),
        USER_CENTER_CONNECT_FAIL(new CommonException(1028,"连接注册中心失败")),
        USER_CENTER_REGISTE_FAIL(new CommonException(1029,"用户中心注册失败")),

        PHONENO_INPUT_ERROR(new CommonException(2030,"手机号不符合规则")),
        USER_CENTER_UPDATE_FAIL(new CommonException(2031,"注册中心修改用户信息失败")),
        PARAM_NOT_COMPLETE(new CommonException(2032,"传入参数不完整")),
        USER_CENTER_SERVER_FAIL(new CommonException(2033,"注册中心暂不提供服务")),
        USER_CENTER_VALIDATE_FAIL(new CommonException(2034,"用户中心登陆验证失败，用户名或密码不正确")),
        USER_CENTER_MERGE_FAIL(new CommonException(2035,"合并失败（无主用户信息或登录名重复)")),
        USER_CENTER_EXIST_PHONE(new CommonException(2040,"合并失败,该登录名的手机或邮箱存在多条数据，请更换手机或邮箱合并")),
        USER_CENTER_PWD_WRONG(new CommonException(2036,"注册中心同步修改密码出错:-->用户名或原密码不正确")),
        USER_CENTER_PWD_EQUALS(new CommonException(2037,"注册中心同步修改密码出错:-->原密码不能与新密码相同")),
        USER_CENTER_RESETPWD_FAIL(new CommonException(2038,"注册中心重置密码失败")),
        CUSCORP_NOT_EXIS(new CommonException(2039,"查找的企业不存在")),
        CUSCORP_NOT_FOUND(new CommonException(2039,"此企业未查询到")),

        USER_CENTER_RESULT_FAIL(new CommonException(2041,"注册中心查询结果无数据或查询异常")),
        USER_CENTER_NOT_RETURN_PHONE(new CommonException(2047,"注册中心未返回手机号")),
        SERVICE_UNAVAILABLE(new CommonException(2042,"服务不可用  (此异常是控制用户注册和修改密码开关异常)")),
        ACCESS_CHANNEL_ERROR(new CommonException(2043,"访问渠道不正确")),
        USER_CARD_STATE_ERROR(new CommonException(2044,"输入的卡状态有误")),
        ALLOW_PAY_MODEL_ERROR(new CommonException(2045,"输入信息有误")),
        PAY_MODEL_NOT_EXIST(new CommonException(2046,"此卡业务设置信息不存在")),

        ID_TYPE_NOT_NULL (new CommonException( 2045,"证件类型不为空")),
        ID_NO_FORMAT_ERROR (new CommonException( 2055,"用户身份证格式不正确")),

        OLD_EQUAL_NEW(new CommonException(3042,"输入的新密码等于旧密码")),
        PWD_NOT_NULL(new CommonException(3043,"用户名或密码错误")),
        NEW_NOTEQUAL_CONFIRM(new CommonException(3041,"两次输入的密码不相同")),
        PWD_NOTEQUAL_THIRD(new CommonException(3044,"输入的新密码不能与最近三次密码相同"));

        private CommonException commonException;

        UserCommonException(CommonException commonException){
            this.commonException = commonException;
        }

        public CommonException getCommonException() {
            return commonException;
        }

        public void setCommonException(CommonException commonException) {
            this.commonException = commonException;
        }

        public static void show(){
            for(UserCommonException u : UserCommonException.values()){
                System.out.println(u + "： UserCommonException =" + u.getCommonException());
            }
        }
    }

}<file_sep>-- 秒杀执行存储过程
DELIMITER $$ -- console; 转换为 $$
-- 定义存储过程
-- 参数：in 输入参数；out 输出参数
-- row_count()返回上一条修改类型sql（delete、insert、update）的影响行数
-- row_count():0未修改数据 >0表示修改的行数 <0sql错误或者未执行sql

CREATE PROCEDURE `jeesite`.`execute_seckill`(
	IN v_seckill_id BIGINT ,
	IN v_phone BIGINT ,
	IN v_kill_time TIMESTAMP ,
	OUT r_result INT
)
BEGIN

	DECLARE insert_count int DEFAULT 0 ;
	START TRANSACTION ;
	INSERT IGNORE INTO success_killed(seckill_id ,user_phone ,create_time)
	VALUES(v_seckill_id ,v_phone ,v_kill_time);
	SELECT ROW_COUNT() INTO insert_count;
	IF(insert_count = 0) THEN
		ROLLBACK;
		SET r_result = 0;
	ELSEIF(insert_count < 0) THEN
		ROLLBACK;
		SET r_result = -1;
	ELSE
		UPDATE seckill SET number = number -1
		WHERE seckill_id = v_seckill_id
		AND (v_kill_time BETWEEN start_time AND end_time)
		AND number > 0;
		SELECT ROW_COUNT() INTO insert_count ;
		IF(insert_count = 0) THEN
			ROLLBACK;
			SET r_result = 0;
		ELSEIF(insert_count < 0) THEN
			ROLLBACK;
			SET r_result = -1;
		ELSE
			COMMIT;
			SET r_result = 1;
		END IF;

	END IF;
END $$

-- 储存过程结束

show create procedure execute_seckill

DELIMITER ;
set @r_result=-3;
call execute_seckill(1001,13502178891,now(),@r_result);
SELECT @r_result;

--储存过程优化：事务行级锁持有的时间<file_sep>package com.thinkgem.jeesite.common.pattern.singleton;

/**
 * 懒汉单例模式
 * 写法简单，适合简单、小的对象创建；
 * 当创建一个非常复杂、非常大I/O操作、非常耗内存的对象时，不宜采用；
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/6/28 16:56
 */
public class LazySingletonPattern {

    //方法1 声明为常量
    private static final LazySingletonPattern instance = new LazySingletonPattern();

    //方法2 静态代码块
    /*private static LazySingletonPattern instance = null;
    static{
        instance = new LazySingletonPattern();
    }*/

    //构造方法私有
    private LazySingletonPattern(){}

    public static LazySingletonPattern getInstance() {
        return instance;
    }
}<file_sep>package com.thinkgem.jeesite.common.security.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019/4/14 15:59
 * 认证
 */
public class IniRealmTest {
    private static final IniRealm iniRealm = new IniRealm("classpath:user.ini");

    @Test
    public void testAuthentication() {

        //1. 构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(iniRealm);

        //2. 主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        //3. 登录
        UsernamePasswordToken token = new UsernamePasswordToken("Mark","<PASSWORD>");
        subject.login(token);

        System.out.println("isAuthenticated : " + subject.isAuthenticated());

        //4. 授权
        subject.checkRole("admin");
        subject.checkPermissions("user:delete","user:update");
    }


}
<file_sep>package com.thinkgem.jeesite.common.pattern.pattern2;

import lombok.ToString;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019-04-24 21:04
 */
@ToString
public class StatisticsDisplay implements Observer,DisplayElement{
    private float temperature;
    private float humidity;
    private float pressure;
    private WeatherData weatherData;

    public StatisticsDisplay(Subject weatherData){
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temperature,float humidity,float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        display();
    }

    @Override
    public void update(Subject subject){
        if(subject instanceof WeatherData){
            weatherData = (WeatherData)subject;
        }
        this.temperature = weatherData.getTemperature();
        this.humidity = weatherData.getHumidity();
        this.pressure = weatherData.getPressure();
        display();
    }

    @Override
    public void display() {
        System.out.println("StatisticsDisplay = " + toString());
    }

}
<file_sep>package com.thinkgem.jeesite.common.security.encrypt.util;

import com.thinkgem.jeesite.common.security.encrypt.enums.EnumAuthCodeAlgorithm;
import com.thinkgem.jeesite.common.utils.NumberUtil;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/8/16 9:30
 */
@Slf4j
public class MessageAuthCodeUtil {

    public static byte[] encode(EnumAuthCodeAlgorithm authCodeAlgorithm,byte[] byteData, byte[] keyData) throws NoSuchAlgorithmException, InvalidKeyException {
        Mac mac = Mac.getInstance(authCodeAlgorithm.name());
        SecretKey secretKey = new SecretKeySpec(keyData, authCodeAlgorithm.name());
        mac.init(secretKey);
        return mac.doFinal(byteData);
    }

    public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {

        String dataString = "ZGL";

        for (EnumAuthCodeAlgorithm authCodeAlgorithm : EnumAuthCodeAlgorithm.values()){
            log.info(authCodeAlgorithm.getValue());
            SecretKey secretKey = KeyUtil.generateKey(authCodeAlgorithm);
            log.info("消息验证码的密钥： {}", NumberUtil.bytesToStrHex(secretKey.getEncoded()));
            byte[] mac = encode(authCodeAlgorithm,dataString.getBytes(),secretKey.getEncoded());
            log.info("消息验证码后数据: {}", NumberUtil.bytesToStrHex(mac));
        }

        log.info("前后台通用HmacMD5消息验证码: {}",NumberUtil.bytesToStrHex(encode(EnumAuthCodeAlgorithm.HmacMD5, "消息摘要".getBytes(),"HmacMD5".getBytes())));
        log.info("前后台通用HmacSHA256消息验证码: {}",NumberUtil.bytesToStrHex(encode(EnumAuthCodeAlgorithm.HmacSHA256, "消息摘要".getBytes(),"HmacSHA256".getBytes())));
    }
}<file_sep>package com.thinkgem.jeesite.common.pattern.strategy_plus.behavior;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019/5/2 20:27
 * @Description 封装飞行行为接口
 */
public interface FlyBehavior {
    /**
     * 飞行行为
     */
    void fly();
}
<file_sep>package com.thinkgem.jeesite.common.security.shiro;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019/4/14 16:45
 */
public class CustomRealm extends AuthorizingRealm {
    //用户
    public static final Map<String,String> USERS = new HashMap<>();
    //角色
    public static final Set<String> ROLES = new HashSet<>();
    //权限
    public static final Set<String> PERMISSIONS = new HashSet<>();
    {
        USERS.put("Mark","283538989cef48f3d7d8a1c1bdf2008f");
        ROLES.add("admin");
        PERMISSIONS.add("user:delete");
        PERMISSIONS.add("user:update");
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName = (String)token.getPrincipal();
        if(USERS.get(userName) == null){
           return null;
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName,USERS.get(userName),"customRealm");
        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("Mark"));
        return simpleAuthenticationInfo;
    }


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String userName = (String)principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(ROLES);
        simpleAuthorizationInfo.setStringPermissions(PERMISSIONS);
        return simpleAuthorizationInfo;
    }

    public static void main(String[] args) {
        Md5Hash md5Hash = new Md5Hash("123456");
        System.out.println("md5Hash = " + md5Hash);
        md5Hash = new Md5Hash("123456","Mark");
        System.out.println("md5Hash salt = " + md5Hash);
    }


}
<file_sep>package com.thinkgem.jeesite.common.pattern.chain;

import static org.junit.Assert.*;

public class HandlerProcessorTest {
    public static void main(String[] args) {
        HandlerProcessor handlerProcessor = new HandlerProcessor();
        handlerProcessor.addHandler(new ComplainHandler())
                .addHandler(new FanHandler())
                .addHandler(new NewLocHandler())
                .addHandler(new SpamHandler()).handleRequest(" email test");

    }

}<file_sep>package com.thinkgem.jeesite.common.enumdemo;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/8/31 15:50
 */
public class CommonExceptionsTest {
    public static void main(String[] args) {
        CommonExceptions.UserCommonException.show();
        throw CommonExceptions.UserCommonException.CUST_NOT_REGISTER.getCommonException();
    }
}<file_sep>package com.thinkgem.jeesite.common.security.encrypt.util;


import com.thinkgem.jeesite.common.security.encrypt.enums.EnumSignatureAlgorithm;
import com.thinkgem.jeesite.common.utils.NumberUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * 数字证书工具类
 * @author ZGL
 *
 */
public class DigitalSignatureUtil {
	/**
	 * 私钥签名
	 * @param signatureAlgorithm 签名算法
	 * @param strHexPrivateKey 16进制字符串私钥
	 * @param byteData
	 * @return
	 * @throws Exception
	 */
	public static byte[] sign(EnumSignatureAlgorithm signatureAlgorithm, String strHexPrivateKey, byte[] byteData) throws Exception{
		return sign(signatureAlgorithm, NumberUtil.strHexToBytes(strHexPrivateKey), byteData);
	}
	
	/**
	 * 私钥签名
	 * @param signatureAlgorithm 签名算法
	 * @param bytePrivateKey  二进制私钥
	 * @param byteData 待签名数据
	 * @return
	 * @throws Exception
	 */
	public static byte[] sign(EnumSignatureAlgorithm signatureAlgorithm,byte[] bytePrivateKey,byte[] byteData) throws Exception{
		Security.addProvider(new BouncyCastleProvider());
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bytePrivateKey);
		KeyFactory keyFactory = KeyFactory.getInstance(signatureAlgorithm.getKeyAlgorithm().name());
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		return sign(signatureAlgorithm, privateKey, byteData);
	}
	
	/**
	 * 私钥签名
	 * @param signatureAlgorithm 签名算法
	 * @param privateKey 私钥
	 * @param byteData 待签名数据
	 * @return
	 * @throws Exception
	 */
	public static byte[] sign(EnumSignatureAlgorithm signatureAlgorithm,PrivateKey privateKey,byte[] byteData) throws Exception{
		Security.addProvider(new BouncyCastleProvider());
		Signature signature = Signature.getInstance(signatureAlgorithm.name());
		signature.initSign(privateKey);
		signature.update(byteData);
		return signature.sign();
	}
	
	
	
	
	
	
	/**
	 * 公钥校验签名
	 * @param signatureAlgorithm
	 * @param strHexPublicKey 16进制字符串公钥
	 * @param byteData 源数据
	 * @param byteSign 签名
	 * @return
	 * @throws Exception
	 */
	public static boolean verify(EnumSignatureAlgorithm signatureAlgorithm,String strHexPublicKey,byte[] byteData,byte[] byteSign) throws Exception {
		return verify(signatureAlgorithm, NumberUtil.strHexToBytes(strHexPublicKey), byteData, byteSign);
	}

	/**
	 * 公钥校验签名
	 * @param signatureAlgorithm 签名算法
	 * @param bytePublicKey 二进制公钥
	 * @param byteData 源数据
	 * @param byteSign 签名
	 * @return
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeySpecException 
	 */
	public static boolean verify(EnumSignatureAlgorithm signatureAlgorithm,byte[] bytePublicKey,byte[] byteData,byte[] byteSign) throws Exception {
		Security.addProvider(new BouncyCastleProvider());
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(bytePublicKey);
		KeyFactory keyFactory = KeyFactory.getInstance(signatureAlgorithm.getKeyAlgorithm().name());
		PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		
		return verify(signatureAlgorithm, publicKey, byteData, byteSign);
	}

	/**
	 * 公钥校验签名
	 * @param signatureAlgorithm 签名算法
	 * @param publicKey 公钥
	 * @param byteData 源数据
	 * @param byteSign 签名
	 * @return
	 * @throws Exception
	 */
	public static boolean verify(EnumSignatureAlgorithm signatureAlgorithm,PublicKey publicKey,byte[] byteData,byte[] byteSign) throws Exception {
		Security.addProvider(new BouncyCastleProvider());
		Signature signature = Signature.getInstance(signatureAlgorithm.name());
		signature.initVerify(publicKey);
		signature.update(byteData);
		return signature.verify(byteSign);
	}

	
	public static void main(String[] args) throws Exception {
		String dataString = "ZGL";
		for (EnumSignatureAlgorithm signatureAlgorithm : EnumSignatureAlgorithm.values()) {
			System.out.println(signatureAlgorithm.name());
			KeyPair keyPair = KeyUtil.generateKeyPair(signatureAlgorithm.getKeyAlgorithm(), null);
			byte[] byteSign = sign(signatureAlgorithm, NumberUtil.bytesToStrHex(keyPair.getPrivate().getEncoded()), dataString.getBytes());
			System.out.println("签名： " + NumberUtil.bytesToStrHex(byteSign));
			System.out.println("校验结果： "+verify(signatureAlgorithm, keyPair.getPublic().getEncoded(), dataString.getBytes(), byteSign));
			System.out.print("\n");
		}
	}
}
<file_sep># Immutable模式>>>想破坏也破坏不了

## 标准类库中用到的Immutable模式
```
表示字符串的java.lang.String类
表示大数字的java.math.BigInteger类
表示正则表达式模式的java.util.regex.Pattern类
基本类型的包装类（wrapper class）、java.lang.Void
```<file_sep>package com.thinkgem.jeesite.common.pattern.strategy;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/7/25 10:39
 */
public class ExecutorRouteLFU implements ExecutorRouteStrategy{
    private static ConcurrentHashMap<String,Integer> lfuItemMap = new ConcurrentHashMap<>();
    @Override
    public String selectRouteRun(List<String> addressList) {
        for(String address:addressList){
            if(!lfuItemMap.containsKey(address)){
                lfuItemMap.put(address,0);
            }
        }
        List<Map.Entry<String,Integer>> itemList = new ArrayList<>(lfuItemMap.entrySet());
        Collections.sort(itemList, Comparator.comparing(Map.Entry::getValue));
        Map.Entry<String, Integer> itemMap = itemList.get(0);
        itemMap.setValue(itemMap.getValue()+1);
        return itemMap.getKey();
    }
}<file_sep>package com.thinkgem.jeesite.common.pattern.chain;

import java.util.ArrayList;
import java.util.List;

/**
 * @author duhongming
 * @version 1.0
 * @description TODO
 * @date 2019-10-05 13:10
 */
public class HandlerProcessor{
    private List<Handler> handlers = new ArrayList<>();

    public HandlerProcessor addHandler(Handler handler){
        handlers.add(handler);
        return this;
    }

    public void handleRequest(String email) {
        for (Handler handler : handlers) {
            if(handler.preHandler(email)) {
                handler.handleRequest(email);
            }
            handler.afterHandler(email);
        }
    }
}
<file_sep>package com.thinkgem.jeesite.common.security.encrypt.util;


import com.thinkgem.jeesite.common.security.encrypt.enums.EnumDigestAlgorithm;
import com.thinkgem.jeesite.common.utils.Exceptions;
import com.thinkgem.jeesite.common.utils.NumberUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.Validate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.*;
import java.security.*;


/**
 * 消息摘要工具类
 * @author ZGL
 *
 */
@Slf4j
public class MessageDigestUtil {

	private static SecureRandom random = new SecureRandom();

	public static byte[] encode(EnumDigestAlgorithm digestAlgorithm, byte[] byteData) throws NoSuchAlgorithmException{
		Security.addProvider(new BouncyCastleProvider());
		return MessageDigest.getInstance(digestAlgorithm.name()).digest(byteData);
	}

	public static byte[] encodeWithSalt(EnumDigestAlgorithm digestAlgorithm, byte[] byteData, byte[] salt) throws NoSuchAlgorithmException{
		Security.addProvider(new BouncyCastleProvider());
		return MessageDigest.getInstance(digestAlgorithm.name()).digest(byteData);
	}

	public static byte[] encodeWithSaltIterations(EnumDigestAlgorithm digestAlgorithm, byte[] byteData, byte[] salt, int iterations){
		try{
			Security.addProvider(new BouncyCastleProvider());
			MessageDigest digest = MessageDigest.getInstance(digestAlgorithm.name());
			if (salt != null) {
				digest.update(salt);
			}

			byte[] result = digest.digest(byteData);

			for (int i = 1; i < iterations; i++) {
				digest.reset();
				result = digest.digest(result);
			}
			return result;
		} catch (GeneralSecurityException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 生成随机的Byte[]作为salt.
	 *
	 * @param numBytes byte数组的大小
	 */
	public static byte[] generateSalt(int numBytes) {
		Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);

		byte[] bytes = new byte[numBytes];
		random.nextBytes(bytes);
		return bytes;
	}

	public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
		String dataString = "ZGL";
		/**
		 *
		 * MD是消息摘要（Message Digest），它们都不安全了。
		 * SHA-1已经不安全了，SHA-2还尚未被攻破。
		 */
		for (EnumDigestAlgorithm digestAlgorithm : EnumDigestAlgorithm.values()) {
			byte[] md = encode(digestAlgorithm, dataString.getBytes());
			log.info("{},文本摘要信息: {}", digestAlgorithm.getValue(), NumberUtil.bytesToStrHex(md));
		}


		log.info("前后台通用MD5摘要信息: {}",NumberUtil.bytesToStrHex(encode(EnumDigestAlgorithm.MD5, "消息摘要".getBytes())));
		log.info("前后台通用SHA256摘要信息: {}",NumberUtil.bytesToStrHex(encode(EnumDigestAlgorithm.SHA256, "消息摘要".getBytes())));

		byte[] bytes = new MessageDigestUtil().inputStream2ByteArray("E:\\personal-software-auto\\Hadoop\\1.Hadoop\\hadoop-3.1.1.tar.gz");
		//文件指纹，参见文件hadoop-3.1.1.tar.gz.mds.txt
		for (EnumDigestAlgorithm digestAlgorithm : EnumDigestAlgorithm.values()) {
			byte[] md = encode(digestAlgorithm,bytes);
			log.info("{},文件摘要信息: {}", digestAlgorithm.getValue(),NumberUtil.bytesToStrHex(md));
		}
	
	}

	private byte[] inputStream2ByteArray(String filePath) throws IOException {

		InputStream in = new FileInputStream(filePath);
		byte[] data = toByteArray(in);
		in.close();

		return data;
	}

	private byte[] toByteArray(InputStream in) throws IOException {

		ByteArrayOutputStream out = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024 * 4];
		int n = 0;
		while ((n = in.read(buffer)) != -1) {
			out.write(buffer, 0, n);
		}
		return out.toByteArray();
	}
}
<file_sep>[users]
Mark=123456,admin

[roles]
admin=user:delete,user:update<file_sep>package com.thinkgem.jeesite.common.pattern.pattern2;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019-04-24 21:43
 */
public interface DisplayElement {
    void display();
}
<file_sep>package com.thinkgem.jeesite.common.security.encrypt.util;


import com.thinkgem.jeesite.common.security.encrypt.enums.EnumCipherAlgorithm;
import com.thinkgem.jeesite.common.security.encrypt.enums.EnumKeyAlgorithm;
import com.thinkgem.jeesite.common.utils.NumberUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;



/**
 * 加解密工具类
 * 
 * @author ZGL
 * 
 */
@Slf4j
public class CipherUtil {

	/**
	 * 加密，非对称加密一般来说是公钥加密，私钥解密
	 * @param cipherAlgorithm 加密算法
	 * @param strHexKey 16进制字符串钥匙
	 * @param byteData 待加密数据
	 * @return
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte[] encrypt(EnumCipherAlgorithm cipherAlgorithm, String strHexKey, byte[] byteData)
			throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
		return encrypt(cipherAlgorithm, NumberUtil.strHexToBytes(strHexKey), byteData);
		
	}
	
	/**
	 * 加密，非对称加密一般来说是公钥加密，私钥解密
	 * @param cipherAlgorithm 加密算法
	 * @param byteKey 二进制钥匙
	 * @param byteData 待加密数据
	 * @return
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte[] encrypt(EnumCipherAlgorithm cipherAlgorithm,  byte[] byteKey, byte[] byteData)
			throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
		Security.addProvider(new BouncyCastleProvider());
		// 生成秘密密钥或公钥
		Key key = null;
		switch (cipherAlgorithm.getKeyAlgorithm()) {
			case DES:
			case DESede:
			case AES:
			case IDEA:
			{
				key = new SecretKeySpec(byteKey, cipherAlgorithm.getKeyAlgorithm().name());
				break;
			}
			case RSA:
			case DSA:
			case ElGamal:
			{
				try {
					// 尝试获取公钥
					X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
							byteKey);
					key = KeyFactory.getInstance(cipherAlgorithm.getKeyAlgorithm().name())
							.generatePublic(x509EncodedKeySpec);
					break;
				} catch (Exception e) {
					try {
						// 尝试获取私钥
						PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
								byteKey);
						key = KeyFactory.getInstance(cipherAlgorithm.getKeyAlgorithm().name())
								.generatePrivate(pkcs8EncodedKeySpec);
						break;
					} catch (Exception e2) {
						break;
					}
				}
				
			}
			default:
				break;
		}

		return encrypt(cipherAlgorithm, key, byteData);
	}
	
	/**
	 * 解密，非对称加密一般来说是公钥加密，私钥解密
	 * @param cipherAlgorithm 加密算法
	 * @param byteData 待解密数据
	 * @param key 钥匙
	 * @return
	 * @throws NoSuchPaddingException 
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeyException 
	 * @throws BadPaddingException 
	 * @throws IllegalBlockSizeException 
	 * @throws Exception
	 */
	public static byte[] encrypt(EnumCipherAlgorithm cipherAlgorithm, Key key, byte[] byteData)
			throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		String algorithm = key.getAlgorithm();
		if(cipherAlgorithm != null){
			algorithm = cipherAlgorithm.getValue();
		}
		Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.ENCRYPT_MODE, key);
		return cipher.doFinal(byteData);
	}
	
	
	
	
	
	
	
	/**
	 * 解密，非对称加密一般来说是公钥加密，私钥解密
	 * @param cipherAlgorithm 加密算法
	 * @param strHexKey 16进制字符串钥匙
	 * @param byteData 待解密数据
	 * @return
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte[] decrypt(EnumCipherAlgorithm cipherAlgorithm,  String strHexKey, byte[] byteData) 
			throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
		return decrypt(cipherAlgorithm, NumberUtil.strHexToBytes(strHexKey), byteData);
	}

	/**
	 * 解密，非对称加密一般来说是公钥加密，私钥解密
	 * @param cipherAlgorithm 加密算法
	 * @param byteKey 二进制钥匙
	 * @param byteData 待解密数据
	 * @return
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte[] decrypt(EnumCipherAlgorithm cipherAlgorithm,  byte[] byteKey, byte[] byteData) 
			throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
		Security.addProvider(new BouncyCastleProvider());
		// 生成秘密密钥或公钥
		Key key = null;
		switch (cipherAlgorithm.getKeyAlgorithm()) {
			case DES:
			case DESede:
			case AES:
			case IDEA:
			{
				key = new SecretKeySpec(byteKey, cipherAlgorithm.getKeyAlgorithm().name());
				break;
			}
			case RSA:
			case DSA:
			case ElGamal:
			{
				try {
					// 尝试获取私钥
					PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
							byteKey);
					key = KeyFactory.getInstance(cipherAlgorithm.getKeyAlgorithm().name())
							.generatePrivate(pkcs8EncodedKeySpec);
					break;
				} catch (Exception e) {
					try {
						// 尝试获取公钥
						X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
								byteKey);
						key = KeyFactory.getInstance(cipherAlgorithm.getKeyAlgorithm().name())
								.generatePublic(x509EncodedKeySpec);
						break;
					} catch (Exception e2) {
						break;
					}
				}
			}
			default:
				break;
		}
		return decrypt(cipherAlgorithm, key, byteData);
	}
	/**
	 * 解密，非对称加密一般来说是公钥加密，私钥解密
	 * @param cipherAlgorithm 加密算法
	 * @param key 钥匙
	 * @param byteData 待解密数据
	 * @return
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchPaddingException
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 */
	public static byte[] decrypt(EnumCipherAlgorithm cipherAlgorithm, Key key, byte[] byteData) 
			throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		String algorithm = key.getAlgorithm();
		if(cipherAlgorithm != null){
			algorithm = cipherAlgorithm.getValue();
		}
		Cipher cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.DECRYPT_MODE, key);
		return cipher.doFinal(byteData);
	}

	/**
	 * JS、JAVA通用：DES加密
	 * @param key
	 * @param plaintext
	 * @return
	 */
	public static String encodeDES(String key,String plaintext){
		try{
			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), EnumKeyAlgorithm.DES.name());
			//现在，获取数据并加密
            byte[] e = encrypt(EnumCipherAlgorithm.DES_ECB_PKCS5Padding,keyspec.getEncoded(),plaintext.getBytes());
            //现在，获取数据并编码
			byte[] temp = Base64.encodeBase64(e);
			return IOUtils.toString(temp,"UTF-8");
		}catch(Throwable e){
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * JS、JAVA通用：DESede加密
	 * @param key
	 * @param plaintext
	 * @return
	 */
	public static String encodeDESede(String key,String plaintext){
		try{
			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), EnumKeyAlgorithm.DESede.name());
			//现在，获取数据并加密
			byte[] e = encrypt(EnumCipherAlgorithm.DESede_ECB_PKCS5Padding,keyspec.getEncoded(),plaintext.getBytes());
			//现在，获取数据并编码
			byte[] temp = Base64.encodeBase64(e);
			return IOUtils.toString(temp,"UTF-8");
		}catch(Throwable e){
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * JS、JAVA通用：AES加密
	 * @param key
	 * @param plaintext
	 * @return
	 */
	public static String encodeAES(String key,String plaintext){
		try{
			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), EnumKeyAlgorithm.AES.name());
			//现在，获取数据并加密
			byte[] e = encrypt(EnumCipherAlgorithm.AES_ECB_PKCS5Padding,keyspec.getEncoded(),plaintext.getBytes());
			//现在，获取数据并编码
			byte[] temp = Base64.encodeBase64(e);
			return IOUtils.toString(temp,"UTF-8");
		}catch(Throwable e){
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * JS、JAVA通用：DES解密
	 * @param key
	 * @param ciphertext
	 * @return
	 * @throws Exception
	 */
	public static String decodeDES(String key,String ciphertext) {
        try {
			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), EnumKeyAlgorithm.DES.name());
            // 真正开始解码操作
            byte[] temp = Base64.decodeBase64(ciphertext);
            // 真正开始解密操作
            byte[] e = decrypt(EnumCipherAlgorithm.DES_ECB_PKCS5Padding,keyspec.getEncoded(),temp);
            return IOUtils.toString(e,"UTF-8");
        }catch(Throwable e){
            e.printStackTrace();
            return null;
        }
	}

	/**
	 * JS、JAVA通用：DESede解密
	 * @param key
	 * @param ciphertext
	 * @return
	 * @throws Exception
	 */
	public static String decodeDESede(String key,String ciphertext) {
		try {
			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), EnumKeyAlgorithm.DESede.name());
			// 真正开始解码操作
			byte[] temp = Base64.decodeBase64(ciphertext);
			// 真正开始解密操作
			byte[] e = decrypt(EnumCipherAlgorithm.DESede_ECB_PKCS5Padding,keyspec.getEncoded(),temp);
			return IOUtils.toString(e,"UTF-8");
		}catch(Throwable e){
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * JS、JAVA通用：AES解密
	 * @param key
	 * @param ciphertext
	 * @return
	 * @throws Exception
	 */
	public static String decodeAES(String key,String ciphertext) {
		try {
			SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), EnumKeyAlgorithm.AES.name());
			// 真正开始解码操作
			byte[] temp = Base64.decodeBase64(ciphertext);
			// 真正开始解密操作
			byte[] e = decrypt(EnumCipherAlgorithm.AES_ECB_PKCS5Padding,keyspec.getEncoded(),temp);
			return IOUtils.toString(e,"UTF-8");
		}catch(Throwable e){
			e.printStackTrace();
			return null;
		}
	}

	public static void main(String[] args) throws Exception {

		try {
			String dataString = "ZGL";
			for (EnumCipherAlgorithm cipherAlgorithm : EnumCipherAlgorithm.values()) {
				log.info(cipherAlgorithm.getValue());
				if(EnumKeyAlgorithm.getSymmetric().contains(cipherAlgorithm.getKeyAlgorithm())){
                    /**
                     * 对称密码（共享密钥密码）- 用相同的密钥进行加密和解密
                     * DES（data encryption standard）- 淘汰
                     * 3DES（triple DES）- 目前被银行机构使用
                     * AES（advanced encryption standard）- 方向
                     * IDEA用于邮件加密，避开美国法律限制 – 国产
                     */
				    SecretKey secretKey = KeyUtil.generateKey(cipherAlgorithm.getKeyAlgorithm(), null);
				    log.info("对称加密的密钥： {}", NumberUtil.bytesToStrHex(secretKey.getEncoded()));
					byte[] e = encrypt(cipherAlgorithm,NumberUtil.bytesToStrHex(secretKey.getEncoded()), dataString.getBytes());
					log.info("对称加密后数据： {}", NumberUtil.bytesToStrHex(e));
					byte[] d = decrypt(cipherAlgorithm, secretKey.getEncoded(), e);
					log.info("对称解密后数据： {}", new String(d));
				}else{
                    /**
                     * 公钥密码(非对称密码) - 用公钥加密，用私钥解密
                     * RSA
                     */
					KeyPair keyPair = KeyUtil.generateKeyPair(cipherAlgorithm.getKeyAlgorithm(), null);
					log.info("非对称加密的公钥： {}\n非对称加密的私钥： {}", NumberUtil.bytesToStrHex(keyPair.getPublic().getEncoded()), NumberUtil.bytesToStrHex(keyPair.getPrivate().getEncoded()));
					byte[] e = encrypt(cipherAlgorithm, keyPair.getPublic().getEncoded(),dataString.getBytes());
					log.info("非对称加密后数据： {}", NumberUtil.bytesToStrHex(e));
					byte[] d = decrypt(cipherAlgorithm, keyPair.getPrivate().getEncoded(), e);
					log.info("非对称解密后数据： {}", new String(d));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		//DES的key长度为8位的字符串，否则会报错
		log.info("前后台通用DES对称加密：{}",encodeDES("des@enc@","我有一个消息"));
		log.info("前后台通用DES对称解密：{}",decodeDES("des@enc@","06tpmY+9V9mPI6AaHXO+IgeLDlDkWUbN"));

		//DESede的key长度为16位的字符串，否则会报错
		log.info("前后台通用DESede对称加密：{}",encodeDESede("@desede@encrypt@","我有一个消息"));
		log.info("前后台通用DESede对称解密：{}",decodeDESede("@desede@encrypt@","iYLomPjfeaoRdolL3kVdVM8I0zZuZyHk"));

		//AES的key长度为16位的字符串，否则会报错
		log.info("前后台通用AES对称加密：{}",encodeAES("aes@encrypt@key@","我有一个消息"));
		log.info("前后台通用AES对称解密：{}",decodeAES("aes@encrypt@key@","<KEY>));

		//RSA每次加密后的数据都不一样
		String e = encryptRSA("我有一个消息");
		log.info("前后台通用RSA非对称加密： {}", e);
		String d = decryptRSA(e);
		log.info("前后台通用RSA非对称解密： {}", d);
	}

	/**
	 * 从字符串中加载公钥
	 * @return
	 * @throws Exception 加载公钥时产生的异常
	 */
	private static RSAPublicKey loadPublicKeyByStr() throws Exception {
		String publicKey = "<KEY>";
		try {
			KeyFactory keyFactory = KeyFactory.getInstance(EnumCipherAlgorithm.RSA_ECB_PKCS1Padding.getKeyAlgorithm().name());
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
			return (RSAPublicKey) keyFactory.generatePublic(keySpec);
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此算法");
		} catch (InvalidKeySpecException e) {
			throw new Exception("公钥非法");
		} catch (NullPointerException e) {
			throw new Exception("公钥数据为空");
		}
	}

	/**
	 * 从字符串中加载私钥
	 * @return
	 * @throws Exception
	 */
	public static RSAPrivateKey loadPrivateKeyByStr() throws Exception {
		String privateKey = "<KEY>";
		try {
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey.getBytes()));
			KeyFactory keyFactory = KeyFactory.getInstance(EnumCipherAlgorithm.RSA_ECB_PKCS1Padding.getKeyAlgorithm().name());
			return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此算法");
		} catch (InvalidKeySpecException e) {
			throw new Exception("私钥非法");
		} catch (NullPointerException e) {
			throw new Exception("私钥数据为空");
		}
	}

	/**
	 * 公钥加密过程
	 * @param plainTextData 明文数据
	 * @return
	 * @throws Exception 加密过程中的异常信息
	 */
	public static String encryptRSA(String plainTextData) throws Exception {
		Cipher cipher = null;
		try {
			// 使用默认RSA
			cipher = Cipher.getInstance(EnumCipherAlgorithm.RSA_ECB_PKCS1Padding.getKeyAlgorithm().name());
			// cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
			cipher.init(Cipher.ENCRYPT_MODE, loadPublicKeyByStr());
			byte[] byteContent = plainTextData.getBytes("utf-8");
			byte[] output = cipher.doFinal(byteContent);
			return new String(Base64.encodeBase64(output));
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此加密算法");
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
			return null;
		} catch (InvalidKeyException e) {
			throw new Exception("加密公钥非法,请检查");
		} catch (IllegalBlockSizeException e) {
			throw new Exception("明文长度非法");
		} catch (BadPaddingException e) {
			throw new Exception("明文数据已损坏");
		}
	}

	/**
	 * 私钥解密过程
	 * @param cipherData 密文数据
	 * @return 明文
	 * @throws Exception 解密过程中的异常信息
	 */
	public static String decryptRSA(String cipherData) throws Exception {
		Cipher cipher = null;
		try {
			// 使用默认RSA
			cipher = Cipher.getInstance(EnumCipherAlgorithm.RSA_ECB_PKCS1Padding.getKeyAlgorithm().name());
			cipher.init(Cipher.DECRYPT_MODE, loadPrivateKeyByStr());
			byte[] byteContent = Base64.decodeBase64(cipherData.getBytes());
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < byteContent.length; i += 128) {
				byte[] subarray = ArrayUtils.subarray(byteContent, i, i + 128);
				byte[] doFinal = cipher.doFinal(subarray);
				sb.append(new String(doFinal, "utf-8"));
			}
			// byte[] output = cipher.doFinal(byteContent);
			String strDate = sb.toString();
			return strDate;
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此解密算法");
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
			return null;
		} catch (InvalidKeyException e) {
			throw new Exception("解密私钥非法,请检查");
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
			throw new Exception("密文长度非法");
		} catch (BadPaddingException e) {
			throw new Exception("密文数据已损坏");
		}
	}

}
<file_sep>package com.thinkgem.jeesite.common.security.encrypt.enums;

public enum EnumDigestAlgorithm {
	MD2("MD2"),
	MD4("MD4"),
	MD5("MD5"),


	SHA1("SHA-1"),
	SHA224("SHA-224"),
	SHA256("SHA-256"),
	SHA384("SHA-384"),
	SHA512("SHA-512"),;
	
	private String value;
	public String getValue() {
		return value;
	}
	
	EnumDigestAlgorithm(String value){
		this.value = value;
	}
	
	
	
}
<file_sep>package com.thinkgem.jeesite.common.enumdemo;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/8/31 15:16
 */
public class CommonException extends RuntimeException {

    protected int errorCode;
    protected String errorInfo;

    public CommonException(int errorCode,String errorInfo){
        this.errorCode=errorCode;
        this.errorInfo=errorInfo;
    }

    @Override
    public String toString() {
        return "CommonException{" +
                "errorCode=" + errorCode +
                ", errorInfo='" + errorInfo + '\'' +
                '}';
    }
}<file_sep>package com.thinkgem.jeesite.common.enumdemo;


/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/7/19 15:37
 */
public class OrganizationType {

    /**
     * 组织机构类型
     */
    public enum TYPE{

        TYPE_QY(1,"企业"),
        TYPE_DW(2,"单位"),
        TYPE_BM(3,"部门");

        private Integer key;
        private String value;

        TYPE(Integer key, String value) {
            this.key = key;
            this.value = value;
        }

        public Integer getKey() {
            return key;
        }

        public void setKey(Integer key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public static void show(){
            for(TYPE v : TYPE.values()){
                System.out.println(v + "： key=" + v.getKey() + " value=" + v.getValue());
            }
        }
    }

    /**
     * 根节点标识
     */
    public enum ROOT_OU{
        ROOT_OU_ELECCAR(1,"电动汽车"),
        ROOT_OU_CORPUSER(2,"企业用户"),
        ROOT_OU_ELEC_MERCHANT(3,"国网商户"),
        ROOT_OU_COMMON_MERCHANT(4,"社会商户"),
        ROOT_OU_PER_MERCHANT(5,"个人商户");

        private Integer key;
        private String value;

        ROOT_OU(Integer key, String value) {
            this.key = key;
            this.value = value;
        }

        public Integer getKey() {
            return key;
        }

        public void setKey(Integer key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public static void show(){
            for(ROOT_OU v : ROOT_OU.values()){
                System.out.println(v + "： key=" + v.getKey() + " value=" + v.getValue());
            }
        }
    }

    /**
     * 注册渠道
     */
    public enum ZQ{

        ZQ_XT(1,"系统"),
        ZQ_YYT(2,"营业厅"),
        ZQ_WZ(3,"网站"),
        ZQ_SJAPP(4,"手机app"),
        ZQ_WX(5,"微信");

        private Integer key;
        private String value;

        ZQ(Integer key, String value) {
            this.key = key;
            this.value = value;
        }

        public Integer getKey() {
            return key;
        }

        public void setKey(Integer key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public static void show(){
            for(ZQ v : ZQ.values()){
                System.out.println(v + "： key=" + v.getKey() + " value=" + v.getValue());
            }
        }
    }

    /**
     * 机构状态
     */
    public enum STATE{

        STATE_ZC(1,"正常"),
        STATE_DJ(2,"冻结"),
        STATE_XH(3,"销户"),
        STATE_LJSC(4,"逻辑删除");

        private Integer key;
        private String value;

        STATE(Integer key, String value) {
            this.key = key;
            this.value = value;
        }

        public Integer getKey() {
            return key;
        }

        public void setKey(Integer key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public static void show(){
            for(STATE v : STATE.values()){
                System.out.println(v + "： key=" + v.getKey() + " value=" + v.getValue());
            }
        }
    }

    /**
     * 机构性质
     */
    public enum OU_PROP{

        OU_PROP_DDGS_ZB(12,"电动汽车公司总部"),
        OU_PROP_DDGS_SGS(13,"电动汽车省公司"),
        OU_PROP_DDGS_DS(14,"电动汽车地市公司"),
        OU_PROP_DDGS_YYT(15,"电动汽车公司营业厅"),
        OU_PROP_QY(21,"企业"),
        OU_PROP_QY_XS(22,"企业下属单位"),
        OU_PROP_DW_ZB(31,"国家电网公司"),
        OU_PROP_DW_SGS(32,"省电网公司"),
        OU_PROP_DW_DS(33,"地市电力公司"),
        OU_PROP_DW_XGS(34,"区县电力公司"),
        OU_PROP_DW_GDS(35,"供电所"),
        OU_PROP_SHQY(41,"社会商户"),
        OU_PROP_SHQY_XS(42,"社会商户下属单位"),
        OU_PROP_GR(50,"个人商户");

        private Integer key;
        private String value;

        OU_PROP(Integer key, String value) {
            this.key = key;
            this.value = value;
        }

        public Integer getKey() {
            return key;
        }

        public void setKey(Integer key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public static void show(){
            for(OU_PROP v : OU_PROP.values()){
                System.out.println(v + "： key=" + v.getKey() + " value=" + v.getValue());
            }
        }
    }

    /**
     * 叶子节点
     */
    public enum OU_IS_LEAF{

        OU_IS_LEAF_TRUE(1,"叶子节点"),
        OU_IS_LEAF_FALSE(0,"不是叶子节点");

        private Integer key;
        private String value;

        OU_IS_LEAF(Integer key, String value) {
            this.key = key;
            this.value = value;
        }

        public Integer getKey() {
            return key;
        }

        public void setKey(Integer key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public static void show(){
            for(OU_IS_LEAF v : OU_IS_LEAF.values()){
                System.out.println(v + "： key=" + v.getKey() + " value=" + v.getValue());
            }
        }
    }
}<file_sep>package com.thinkgem.jeesite.common.pattern.strategy;

import com.thinkgem.jeesite.common.utils.StringUtils;
import org.apache.commons.collections.CollectionUtils;

import java.util.List;
import java.util.Random;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/7/26 23:52
 */
public class ExecutorRouteRandom implements ExecutorRouteStrategy {
    private Random random = new Random();
    @Override
    public String selectRouteRun(List<String> addressList) {
        if(CollectionUtils.isNotEmpty(addressList)){
            return addressList.get(random.nextInt(addressList.size()));
        }
        return StringUtils.EMPTY;
    }
}<file_sep>package com.thinkgem.jeesite.common.security.encrypt.enums;

public enum EnumKeyStoreType {
	JKS("JKS"),PKCS12("PKCS12");
	
	
	private String value;
	public String getValue() {
		return value;
	}
	private EnumKeyStoreType(String value){
		this.value = value;
	}
}
<file_sep>#Single Threaded Execution模式>>>能通过这座桥的只有一个人

## 标准类库中用到的Single Threaded Execution模式
```
import java.util.Collections;
Collections.synchronizedCollection();
Collections.synchronizedList();
Collections.synchronizedMap();
Collections.synchronizedSet();
Collections.synchronizedSortedMap();
Collections.synchronizedSortedSet();
```


## Before/After模式
```
private final Mutex mutex = new Mutex();
mutex.lock();
try{
    unsafeMethod();
}finally {
    mutex.unlock();
}
```<file_sep>package com.thinkgem.jeesite.common.pattern.strategy;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/7/25 10:36
 * 总是执行最后一个
 */
public class ExecutorRouteLast implements ExecutorRouteStrategy {
    @Override
    public String selectRouteRun(List<String> addressList) {
        if(CollectionUtils.isNotEmpty(addressList)){
            return addressList.get(addressList.size()-1);
        }
        return StringUtils.EMPTY;
    }
}<file_sep>package com.thinkgem.jeesite.common.pattern.chain;

/**
 * @author duhongming
 * @version 1.0
 * @description TODO
 * @date 2019-10-05 13:07
 */
public class SpamHandler implements Handler {
    @Override
    public boolean preHandler(String email) {
        return false;
    }

    @Override
    public void handleRequest(String email) {
        System.out.println("SpamHandler" + email);
    }

    @Override
    public void afterHandler(String email) {

    }
}
<file_sep>package com.thinkgem.jeesite.common.pattern.prototype;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/6/19 10:03
 */
public class PrototypeSerializableObject extends SerializableObject{
    private String aaa;
    private int bbb;
    private double ccc;

    public PrototypeSerializableObject(String aaa, int bbb, double ccc) {
        this.aaa = aaa;
        this.bbb = bbb;
        this.ccc = ccc;
    }

    public String getAaa() {
        return aaa;
    }

    public void setAaa(String aaa) {
        this.aaa = aaa;
    }

    public int getBbb() {
        return bbb;
    }

    public void setBbb(int bbb) {
        this.bbb = bbb;
    }

    public double getCcc() {
        return ccc;
    }

    public void setCcc(double ccc) {
        this.ccc = ccc;
    }
}<file_sep>package com.thinkgem.jeesite.multithread.guarded_suspension;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019-05-12 15:56
 */
public class Main {
    public static void main(String[] args) {
        RequestQueue requestQueue = new RequestQueue();
        new ClientThread(3141592L,requestQueue, "Alice").start();
        new ServerThread(6535897L, requestQueue, "Bobby").start();

    }
}
<file_sep># Guarded Suspension模式>>>等我准备好哦

## 阻塞队列
```
//非线程安全的队列
private final Queue<Request> queue = new LinkedList<>();
//线程安全的队列
private final BlockingDeque<Request> queue = new LinkedBlockingDeque<>();
```<file_sep>package com.thinkgem.jeesite.common.pattern.chain;

/**
 * @author duhongming
 * @version 1.0
 * @description TODO
 * @date 2019-10-05 13:09
 */
public class ComplainHandler implements Handler {
    @Override
    public boolean preHandler(String email) {
        return true;
    }

    @Override
    public void handleRequest(String email) {
        System.out.println("ComplainHandler" + email);
    }

    @Override
    public void afterHandler(String email) {

    }
}
<file_sep>package com.thinkgem.jeesite.common.pattern.prototype;

import java.io.*;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/6/19 10:00
 *
 * 抽象类:InputStream/OutputStream
 * 文件流类：FileInputStream/FileOutputStream
 * 字节数字流类：ByteArrayInputStream/ByteArrayOutputStream
 * 对象流类：ObjectInputStream/ObjectOutputStream
 * 管道流类：PipedInputStream/PipedOutputStream
 */
public class PrototypePattern implements Cloneable,Serializable {

    private static final long serialVersionUID = 1L;
    private String string;
    private SerializableObject obj;

    /* 浅复制 */
    public PrototypePattern clone() throws CloneNotSupportedException {
        return (PrototypePattern) super.clone();
    }

    /* 深复制 */
    public PrototypePattern deepClone(){
        PrototypePattern prototype = null;
        //使用try-resource的方式来自动关闭资源，没有必要再手动调用一次close
        /* 写入当前对象的二进制流 */
        try(
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)
        ) {
            objectOutputStream.writeObject(this);
            /* 读出二进制流产生的新对象 */
            try(
                    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
                    ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)
            ){
                return (PrototypePattern) objectInputStream.readObject();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return prototype;
    }

    /* 文件复制 */
    public PrototypePattern fileClone(){
        PrototypePattern prototype = null;
        //使用try-resource的方式来自动关闭资源，没有必要再手动调用一次close
        try(
                FileOutputStream fileOutputStream = new FileOutputStream("PrototypePattern.dat");
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)
        ){
            objectOutputStream.writeObject(this);
            try(
                    FileInputStream fileInputStream = new FileInputStream("PrototypePattern.dat");
                    ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)
            ){
                prototype = (PrototypePattern)objectInputStream.readObject();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return prototype;
    }

    /**
     * 管道复制
     *
     * PipedInputStream，管道输入流应该连接到管道输出流；管道输入流提供要写入管道输出流的所有数据字节。
     * 通常，数据由某个线程从PipedInputStream 对象读取， 并由其他线程将其写入到相应的 PipedOutputStream。
     * 不建议对这两个对象尝试使用单个线程，因为这样可能死锁线程。管道输入流包含一个缓冲区，可在缓冲区限定的 范 围内将读操作和写操作分离开。
     * 如果向连接管道输出流提供数据字节的线程不再存在，则认为该管道已损坏。
     *
     * PipedOutputStream，可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。
     * 通常，数据由某个线程写入PipedOutputStream 对象，并由 其他线程从连接的PipedInputStream 读取。
     * 不建议对这两个对象尝试使用单个线程，因为这样可能会造成该线程死锁。
     * 如果某个线程正从连接的管道输入流中读取数据字节，但该线程不再处于活动状态，则该管道被视为处于毁坏状态。
     *
     * 通过官方API的两段解释，大概能摸到这种实现方式的设计思路了：PipedOutputStream(生产者)生产数据，PipedInputStream(消费者)读取数据，二者同步进行。
     * 但谁也不能先挂掉，一旦挂掉，管道便处于损坏状态。
     *
     * @return
     */
    public PrototypePattern pipeClone(){
        final PrototypePattern[] prototype = {null};
        try {

            PipedOutputStream pipedOutputStream = new PipedOutputStream();
            PipedInputStream pipedInputStream = new PipedInputStream();
            //将管道输出流连接到管道输入流来创建通信管道
            pipedOutputStream.connect(pipedInputStream);

            //创建生产者线程来为管道输出流写入数据.
            new Thread(() -> {
                try {
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(pipedOutputStream);
                    objectOutputStream.writeObject(this);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            //创建消费者线程来从 PipedInputStream对象读取数据
            Thread consumer = new Thread(()->{
                try {
                    ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);
                    prototype[0] = (PrototypePattern)objectInputStream.readObject();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }

            });
            consumer.start();

            //勿必等所有数据读完才继续后面的操作,否则可能造成数据仍未读完便GameOver了.
            consumer.join();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return prototype[0];
    }

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }

    public SerializableObject getObj() {
        return obj;
    }

    public void setObj(SerializableObject obj) {
        this.obj = obj;
    }

}

class SerializableObject implements Serializable {
    private static final long serialVersionUID = 1L;
}<file_sep>package com.thinkgem.jeesite.common.pattern.strategy;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2018/7/26 18:18
 */
public enum ExecutorRouteStrategyEnum {

    FIRST("第一个",new ExecutorRouteFirst()),
    LAST("最后一个",new ExecutorRouteLast()),
    LFU("最不经常使用",new ExecutorRouteLFU()),
    LRU("最近最久未使用",new ExecutorRouteLRU()),
    RANDOM("随机",new ExecutorRouteRandom()),
    ROUND("轮询",new ExecutorRouteRound()),
    BUSYOVER("繁忙转移",new ExecutorRouteBusyover()),
    FAILOVER("故障转移",new ExecutorRouteFailover());

    private String title;
    private ExecutorRouteStrategy routeStrategy;
    ExecutorRouteStrategyEnum(String title,ExecutorRouteStrategy routeStrategy){
        this.title = title;
        this.routeStrategy = routeStrategy;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public ExecutorRouteStrategy getRouteStrategy() {
        return routeStrategy;
    }

    public void setRouteStrategy(ExecutorRouteStrategy routeStrategy) {
        this.routeStrategy = routeStrategy;
    }
}<file_sep>package com.thinkgem.jeesite.common.pattern.strategy_plus.behavior.impl;


import com.thinkgem.jeesite.common.pattern.strategy_plus.behavior.FlyBehavior;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019/5/2 20:29
 * @Description 用翅膀飞
 */
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        //TODO 实现鸭子飞行
        System.out.println("I'm flying!!");
    }
}
<file_sep>package com.thinkgem.jeesite.multithread.single_threaded_execution;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019-05-12 14:41
 */
public class Main {
    public static void main(String[] args) {
        System.out.println("Testing Gate, hit CTRL+C to exit.");
        Gate gate = new Gate();
        new UserThread(gate, "Alice", "Alaska").start();
        new UserThread(gate, "Bobby", "Brazil").start();
        new UserThread(gate, "Chris", "Canad").start();
    }
}
<file_sep>package com.thinkgem.jeesite.common.pattern.strategy_plus;

import com.thinkgem.jeesite.common.pattern.strategy_plus.behavior.impl.FlyWithWings;
import com.thinkgem.jeesite.common.pattern.strategy_plus.behavior.impl.Quack;

/**
 * @Author duhongming
 * @Email <EMAIL>
 * @Date 2019/5/2 20:33
 * @Description 绿头鸭
 */
public class MallardDuck extends Duck {

    public MallardDuck() {
        super();
        super.setFlyBehavior(new FlyWithWings());
        super.setQuackBehavior(new Quack());
    }

    @Override
    public void display() {
        System.out.println("外观是绿头");
    }

    public static void main(String[] args) {
        Duck mallardDuck = new MallardDuck();
        mallardDuck.performAll();
    }
}
