8174f2d0 by lv

0 parents
Showing 1000 changed files with 4889 additions and 0 deletions

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

This diff is collapsed. Click to expand it.
## 引言
JeeSite 是一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Spring MVC、Apache Shiro、MyBatis、Beetl、Bootstrap、AdminLTE)采用经典开发模式,让初学者能够更快的入门并投入到团队开发中去。在线代码生成功能,包括核心模块如:组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、工作流等。采用松耦合设计;界面无刷新,一键换肤;众多账号安全设置,密码策略;在线定时任务配置;支持集群,支持SAAS;支持多数据源;支持微服务。
JeeSite 快速开发平台的主要目的是能够让初级的研发人员快速的开发出复杂的业务功能(经典架构会的人多),让开发者注重专注业务,其余有平台来封装技术细节,降低技术难度,从而节省人力成本,缩短项目周期,提高软件安全质量。
JeeSite 1.x 自 2013 年发布以来已被广大爱好者用到了企业、政府、医疗、金融、互联网等各个领域中,JeeSite 依架构简单精良、易于扩展、大众思维的设计模式,深入开发者的内心,并得到一致好评,于[2016](http://www.oschina.net/project/top_cn_2016?sort=1)[2017](http://www.oschina.net/project/top_cn_2017?sort=1)连续两年获得开源中国《最受欢迎中国开源软件》奖杯,期间也帮助了不少刚毕业的大学生作为入门教材,快速的去实践。
JeeSite 4.x 的升级,作者结合了多年总结和经验,以及各方面的应用案例,对架构完成了一次全部重构,也纳入很多新的思想。不管是从开发者模式、底层架构、逻辑处理还是到用户界面,用户交互体验上都有很大的进步,在不忘学习成本、提高开发效率的情况下,安全方面也做和很多工作,包括:身份认证、密码策略、安全审计、日志收集。
### 4.x 的新特性及优势:<http://jeesite.com/?t=281645>
## 技术选型
* 主框架:Spring Boot 2.0、Spring Framework 5.0、Apache Shiro 1.4、J2Cache
* 持久层:Apache MyBatis 3.4、Hibernate Validation 6.0、Alibaba Druid 1.1
* 视图层:Spring MVC 5.0、Beetl 2.9 替换JSP、Bootstrap 3.3、AdminLTE 2.4
* 前端组件:jQuery 1.12、jqGrid 4.7、layer 3.0、zTree 3.5、jquery-validation
* 工具组件:Apache Commons、Logback 1.1、Jackson 2.8、POI 3.14、Quartz 2.2
* 技术选型详情:<http://jeesite.com/?t=273599>
## 内置功能
* <http://jeesite.com/?t=270187>
## 生态系统
* 分布式微服务系统(Spring Cloud):<https://gitee.com/thinkgem/jeesite4-cloud>
* JFlow工作流引擎:<https://gitee.com/thinkgem/jeesite4-jflow><http://ccflow.org>
* 内容管理模块(CMS):<https://gitee.com/thinkgem/jeesite4-cms>【敬请期待】
## 快速体验
### 在线演示
1. 地址:<http://demo.jeesite.com/>
2. 账号:system
3. 密码:admin
### 本地运行
1. 环境准备:`JDK 1.8``Maven 3.3``MySQL 5.7`
2. 下载源码:<https://gitee.com/thinkgem/jeesite4/attach_files>
3. 打开文件:/web`/src/main/resources/config/application.yml` 配置JDBC连接
4. 执行脚本:/web`/bin/init-data.bat` 初始化数据库
5. 执行脚本:/web`/bin/run-tomcat.bat` 启动服务即可
6. 浏览器访问:<http://127.0.0.1:8980/js/> 账号 system 密码 admin
7. 部署常见问题:<http://jeesite.com/?t=284210>
### 开发环境
1. 部署运行:<http://jeesite.com/?t=267354>
2. 常见问题:<http://jeesite.com/?t=284210>
## 在线文档
* <http://docs.jeesite.com>
## 授权协议声明
1. 已开源的代码,授权协议采用 AGPL v3 + Apache Licence v2 进行发行。
2. 您可以免费使用、修改和衍生代码,但不允许修改后和衍生的代码做为闭源软件发布。
3. 修改后和衍生的代码必须也按照AGPL协议进行流通,对修改后和衍生的代码必须向社会公开。
4. 如果您修改了代码,需要在被修改的文件中进行说明,并遵守代码格式规范,帮助他人更好的理解您的用意。
5. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议、版权声明和其他原作者规定需要包含的说明(请尊重原作者的著作权,不要删除或修改文件中的`@author`信息)。
6. 您可以应用于商业软件,但必须遵循以上条款原则(请协助改进本作品)。
7. 关系平台的发展战略考虑,底层部分代码暂未开源,但这不影响您的二次开发。
8. 请知悉社区版,用户数不可超过100个,最大允许20个用户同时在线(不含匿名)。
## 技术服务与支持
* 没有资金的支撑就很难得到发展,特别是一个好的产品,如果 JeeSite 帮助了您,请为我们点赞。支持我们,您可以得到一些回报,有了这些我们会把公益事业做的更好,回报社区和社会,请给我们一些动力吧,在此非常感谢已支持我们的朋友!
* **联系方式(官方商务)QQ:[1766571055](http://sighttp.qq.com/msgrd?v=1&uin=1766571055)**
* 技术服务支持网页:<http://s.jeesite.com>
# 技术交流方式
* QQ 群号:`127515876``209330483``223507718``709534275``730390092``183903863(外包)`
* 问题反馈:<https://gitee.com/thinkgem/jeesite4/issues>  [【新手必读】](http://www.dianbo.org/9238/stone/tiwendezhihui.htm)
* 码云Gitee:<https://gitee.com/thinkgem/jeesite4>
* GitHub:<https://github.com/thinkgem/jeesite4>
* 作者博客:<https://my.oschina.net/thinkgem>
* **技术服务:**<http://s.jeesite.com>
* 官方网站:<http://jeesite.com>
* 官方论坛:<http://jeesite.net>
* 微信公众号:
![JeeSite4微信公众号](https://static.oschina.net/uploads/space/2018/0302/145133_OGZf_941661.jpg "JeeSite4微信公众号")
## 今后如何升级?
尽量不修改web项目以外的源码项目,如 jeesite-common、jeesite-modele-core,如果修改了,请 Pull Requests 上来,否则代码编码将与官方不同步,将对你的日后升级带来困难。
JeeSite的小版本(4.1.x)升级是非常便捷的,你只需要将 pom.xml 文件中的 parent.version 版本修改到最新版本即可,同版本下你可进行 Maven 快照强制更新,即可将最新版的依赖 jar 更新到本地,下面以 Eclipse 举例,介绍如何操作:
在 web 项目上右键,选择菜单 -> Maven -> Update Project...(或按Alt+F5) -> 点击 Select All 按钮 -> 选择 Force Update of Snapshots/Releases 复选框 -> 点击OK按钮即可。
如果您修改了其它依赖模块代码,这时你需要利用 Git 版本控制工具,与官方仓库代码进行同步,合并代码即可。
如果进行相对大的版本(4.x.x)升级这里我们会附加一个声明,帮助你进行迁移操作,更新日志:<http://jeesite.com/?t=273830>
# Git 全局设置技巧
```
1、提交检出均不转换换行符
git config --global core.autocrlf false
2、拒绝提交包含混合换行符的文件
git config --global core.safecrlf true
```
\ No newline at end of file
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.8
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="jeesite-common">
<wb-resource deploy-path="/" source-path="/src/main/java"/>
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
</wb-module>
</project-modules>
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="1.8"/>
</faceted-project>
disabled=06target
eclipse.preferences.version=1
@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 部署工程版本到Nexus服务器。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean deploy -Dmaven.test.skip=true -Pdeploy
pause
\ No newline at end of file
@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 编译工程Javadoc,生成jar包文件。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean package -Pjavadoc
pause
\ No newline at end of file
@echo off
rem /**
rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
rem *
rem * Author: ThinkGem@163.com
rem */
echo.
echo [信息] 打包安装工程,生成jar包文件。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean install -Dmaven.test.skip=true -Ppackage
pause
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-parent</artifactId>
<version>4.1.5-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>jeesite-common</artifactId>
<packaging>jar</packaging>
<name>JeeSite Common</name>
<url>http://jeesite.com</url>
<inceptionYear>2013-Now</inceptionYear>
<properties>
</properties>
<dependencies>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload.version}</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>${commons-beanutils.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<!-- Apache Tools Ant Tar Zip -->
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>${ant.version}</version>
</dependency>
<!-- Java serialization -->
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<version>${fst.version}</version>
</dependency>
<!-- Json in java -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>${json.version}</version>
</dependency>
<!-- Jackson json -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<!-- Java xml -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</dependency>
<!-- XPath xml -->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</dependency>
<!-- Snake YAML -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<!-- Apache HTTP -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- Jsoup HTTP -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<!-- Email -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>${commons-email.version}</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${activation.version}</version>
</dependency>
<!-- User Agent -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>${UserAgentUtils.version}</version>
</dependency>
<!-- 图片Meta获取
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>${metadata-extractor.version}</version>
</dependency> -->
<!-- 缩略图工具 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>${thumbnailator.version}</version>
</dependency>
<!-- 支持CMYK图片 -->
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>${twelvemonkeys.version}</version>
</dependency>
<!-- 图片验证码生成 -->
<dependency>
<groupId>com.bladejava</groupId>
<artifactId>blade-patchca</artifactId>
<version>${blade-patchca.version}</version>
</dependency>
<!-- File MimeType ContentType -->
<dependency>
<groupId>net.sf.jmimemagic</groupId>
<artifactId>jmimemagic</artifactId>
<version>${jmimemagic.version}</version>
<exclusions>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
<exclusion>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-xc</artifactId>
</exclusion>
<exclusion>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 条形码、二维码生成 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${zxing.version}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${zxing.version}</version>
</dependency>
<!-- POI Office Tools -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-codec</artifactId>
<groupId>commons-codec</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- pinyin4j -->
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>${pinyin4j.version}</version>
</dependency>
<!-- Logging begin -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<!-- common-logging 实际调用 slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<!-- jdk logging 实际调用 slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
<!-- log4j 实际调用 slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<!-- slf4j logback 实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- Logging end -->
<!-- Spring begin -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring end -->
<!-- JUnit Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
</plugins>
</build>
<developers>
<developer>
<id>thinkgem</id>
<name>WangZhen</name>
<email>thinkgem at 163.com</email>
<roles><role>Project lead</role></roles>
<timezone>+8</timezone>
</developer>
</developers>
<organization>
<name>JeeSite</name>
<url>http://jeesite.com</url>
</organization>
</project>
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.callback;
/**
* 方法回调接口
* @author ThinkGem
*/
public interface MethodCallback {
Object execute(Object... params);
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.codec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import com.jeesite.common.lang.ExceptionUtils;
/**
* AES加密解密工具类
* @author ThinkGem
*/
public class AesUtils {
private static final String AES = "AES";
private static final String AES_CBC = "AES/CBC/PKCS5Padding";
private static final int DEFAULT_AES_KEYSIZE = 128; // 生成AES密钥, 默认长度为128位(16字节).
private static final int DEFAULT_IVSIZE = 16; // 生成随机向量, 默认大小为cipher.getBlockSize(), 16字节
private static final SecureRandom RANDOM = new SecureRandom(); // 用于 生成 generateIV随机数对象
private static final String DEFAULT_URL_ENCODING = "UTF-8";
private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125};
/**
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
*/
public static String genKeyString() {
return EncodeUtils.encodeHex(genKey(DEFAULT_AES_KEYSIZE));
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
*/
public static String encode(String input) {
try {
return EncodeUtils.encodeHex(encode(input.getBytes(DEFAULT_URL_ENCODING), DEFAULT_KEY));
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
*/
public static String encode(String input, String key) {
try {
return EncodeUtils.encodeHex(encode(input.getBytes(DEFAULT_URL_ENCODING), EncodeUtils.decodeHex(key)));
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
*/
public static String decode(String input) {
try {
return new String(decode(EncodeUtils.decodeHex(input), DEFAULT_KEY), DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
*/
public static String decode(String input, String key) {
try {
return new String(decode(EncodeUtils.decodeHex(input), EncodeUtils.decodeHex(key)), DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
*/
public static byte[] genKey() {
return genKey(DEFAULT_AES_KEYSIZE);
}
/**
* 生成AES密钥,可选长度为128,192,256位.
*/
public static byte[] genKey(int keysize) {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
keyGenerator.init(keysize);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
} catch (GeneralSecurityException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.
*/
public static byte[] genIV() {
byte[] bytes = new byte[DEFAULT_IVSIZE];
RANDOM.nextBytes(bytes);
return bytes;
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
*/
public static byte[] encode(byte[] input, byte[] key) {
return aes(input, key, Cipher.ENCRYPT_MODE);
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
* @param iv 初始向量
*/
public static byte[] encode(byte[] input, byte[] key, byte[] iv) {
return aes(input, key, iv, Cipher.ENCRYPT_MODE);
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
*/
public static byte[] decode(byte[] input, byte[] key) {
return aes(input, key, Cipher.DECRYPT_MODE);
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
* @param iv 初始向量
*/
public static byte[] decode(byte[] input, byte[] key, byte[] iv) {
return aes(input, key, iv, Cipher.DECRYPT_MODE);
}
/**
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
*
* @param input 原始字节数组
* @param key 符合AES要求的密钥
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
*/
private static byte[] aes(byte[] input, byte[] key, int mode) {
try {
SecretKey secretKey = new SecretKeySpec(key, AES);
Cipher cipher = Cipher.getInstance(AES);
cipher.init(mode, secretKey);
return cipher.doFinal(input);
} catch (GeneralSecurityException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
*
* @param input 原始字节数组
* @param key 符合AES要求的密钥
* @param iv 初始向量
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
*/
private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
try {
SecretKey secretKey = new SecretKeySpec(key, AES);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(AES_CBC);
cipher.init(mode, secretKey, ivSpec);
return cipher.doFinal(input);
} catch (GeneralSecurityException e) {
throw ExceptionUtils.unchecked(e);
}
}
// public static void main(String[] args) {
//
// String s = "hello word!";
// System.out.println(s);
//
// String k = genKeyString();
// System.out.println(k);
// String ss = encode(s, k);
// System.out.println(ss);
// String sss = decode(ss, k);
// System.out.println(sss);
//
// }
}
\ No newline at end of file
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.codec;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.SecureRandom;
import org.apache.commons.lang3.Validate;
import com.jeesite.common.lang.ExceptionUtils;
/**
* 不可逆加密工具类
* @author ThinkGem
*/
public class DigestUtils {
private static SecureRandom random = new SecureRandom();
/**
* 生成随机的Byte[]作为salt密钥.
* @param numBytes byte数组的大小
*/
public static byte[] genSalt(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;
}
/**
* 对字符串进行散列, 支持md5与sha1算法.
* @param input 需要散列的字符串
* @param algorithm 散列算法("SHA-1"、"MD5")
* @param salt
* @param iterations 迭代次数
* @return
*/
public static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
try {
MessageDigest digest = MessageDigest.getInstance(algorithm);
if (salt != null) {
digest.update(salt);
}
byte[] result = digest.digest(input);
for (int i = 1; i < iterations; i++) {
digest.reset();
result = digest.digest(result);
}
return result;
} catch (GeneralSecurityException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* 对文件进行sha1散列.
* @param input 需要散列的流
* @param algorithm 散列算法("SHA-1"、"MD5")
*/
public static byte[] digest(InputStream input, String algorithm) throws IOException {
try {
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
int bufferLength = 8 * 1024;
byte[] buffer = new byte[bufferLength];
int read = input.read(buffer, 0, bufferLength);
while (read > -1) {
messageDigest.update(buffer, 0, read);
read = input.read(buffer, 0, bufferLength);
}
return messageDigest.digest();
} catch (GeneralSecurityException e) {
throw ExceptionUtils.unchecked(e);
}
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.codec;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import com.jeesite.common.io.IOUtils;
/**
* MD5不可逆加密工具类
* @author ThinkGem
*/
public class Md5Utils {
private static final String MD5 = "MD5";
private static final String DEFAULT_ENCODING = "UTF-8";
/**
* 对输入字符串进行md5散列.
* @param input 加密字符串
*/
public static String md5(String input) {
return md5(input, 1);
}
/**
* 对输入字符串进行md5散列.
* @param input 加密字符串
* @param iterations 迭代次数
*/
public static String md5(String input, int iterations) {
try {
return EncodeUtils.encodeHex(DigestUtils.digest(input.getBytes(DEFAULT_ENCODING), MD5, null, iterations));
} catch (UnsupportedEncodingException e) {
return StringUtils.EMPTY;
}
}
/**
* 对输入字符串进行md5散列.
* @param input 加密字符串
*/
public static byte[] md5(byte[] input) {
return md5(input, 1);
}
/**
* 对输入字符串进行md5散列.
* @param input 加密字符串
* @param iterations 迭代次数
*/
public static byte[] md5(byte[] input, int iterations) {
return DigestUtils.digest(input, MD5, null, iterations);
}
/**
* 对文件进行md5散列.
*/
public static byte[] md5(InputStream input) throws IOException {
return DigestUtils.digest(input, MD5);
}
/**
* 获取文件的MD5值
*/
public static String md5File(File file) {
return md5File(file, -1);
}
/**
* 获取文件的MD5值,支持获取文件部分的MD5值
* uploader.md5File(file, 0, 10 * 1024 * 1024)
*/
public static String md5File(File file, int size) {
if (file != null && file.exists()){
try (InputStream in = FileUtils.openInputStream(file)){
byte[] bytes = null;
if (size != -1 && file.length() >= size){
bytes = IOUtils.toByteArray(in, size);
}else{
bytes = IOUtils.toByteArray(in);
}
return EncodeUtils.encodeHex(md5(bytes));
} catch (IOException e) {
return StringUtils.EMPTY;
}
}
return StringUtils.EMPTY;
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.codec;
import java.io.IOException;
import java.io.InputStream;
/**
* SHA-1不可逆加密工具类
* @author ThinkGem
*/
public class Sha1Utils {
private static final String SHA1 = "SHA-1";
/**
* 生成随机的Byte[]作为salt密钥.
* @param numBytes byte数组的大小
*/
public static byte[] genSalt(int numBytes) {
return DigestUtils.genSalt(numBytes);
}
/**
* 对输入字符串进行sha1散列.
*/
public static byte[] sha1(byte[] input) {
return DigestUtils.digest(input, SHA1, null, 1);
}
/**
* 对输入字符串进行sha1散列.
*/
public static byte[] sha1(byte[] input, byte[] salt) {
return DigestUtils.digest(input, SHA1, salt, 1);
}
/**
* 对输入字符串进行sha1散列.
*/
public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
return DigestUtils.digest(input, SHA1, salt, iterations);
}
/**
* 对文件进行sha1散列.
*/
public static byte[] sha1(InputStream input) throws IOException {
return DigestUtils.digest(input, SHA1);
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.collect;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import com.jeesite.common.lang.StringUtils;
/**
* Map工具类,实现 Map <-> Bean 互相转换
* @author ThinkGem
* @version 2015-01-15
*/
public class MapUtils extends org.apache.commons.collections.MapUtils {
public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap<K, V>();
}
public static <K, V> HashMap<K, V> newHashMap(int initialCapacity) {
return new HashMap<K, V>(initialCapacity);
}
public static <K, V> HashMap<K, V> newHashMap(Map<? extends K, ? extends V> map) {
return new HashMap<K, V>(map);
}
public static <K, V> LinkedHashMap<K, V> newLinkedHashMap() {
return new LinkedHashMap<K, V>();
}
public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(Map<? extends K, ? extends V> map) {
return new LinkedHashMap<K, V>(map);
}
public static <K, V> ConcurrentMap<K, V> newConcurrentMap() {
return new ConcurrentHashMap<K, V>();
}
@SuppressWarnings("rawtypes")
public static <K extends Comparable, V> TreeMap<K, V> newTreeMap() {
return new TreeMap<K, V>();
}
public static <K, V> TreeMap<K, V> newTreeMap(SortedMap<K, ? extends V> map) {
return new TreeMap<K, V>(map);
}
public static <C, K extends C, V> TreeMap<K, V> newTreeMap(Comparator<C> comparator) {
return new TreeMap<K, V>(comparator);
}
public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(Class<K> type) {
return new EnumMap<K, V>((type));
}
public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(Map<K, ? extends V> map) {
return new EnumMap<K, V>(map);
}
public static <K, V> IdentityHashMap<K, V> newIdentityHashMap() {
return new IdentityHashMap<K, V>();
}
/**
* List<Map<String, V>转换为List<T>
* @param clazz
* @param list
*/
public static <T, V> List<T> toObjectList(Class<T> clazz, List<HashMap<String, V>> list) throws IllegalAccessException,
InvocationTargetException, NoSuchMethodException, InstantiationException {
List<T> retList = new ArrayList<T>();
if (list != null && !list.isEmpty()) {
for (HashMap<String, V> m : list) {
retList.add(toObject(clazz, m));
}
}
return retList;
}
/**
* 将Map转换为Object
* @param clazz 目标对象的类
* @param map 待转换Map
*/
public static <T, V> T toObject(Class<T> clazz, Map<String, V> map) throws InstantiationException, IllegalAccessException,
InvocationTargetException {
T object = clazz.newInstance();
return toObject(object, map);
}
/**
* 将Map转换为Object
* @param clazz 目标对象的类
* @param map 待转换Map
* @param toCamelCase 是否去掉下划线
*/
public static <T, V> T toObject(Class<T> clazz, Map<String, V> map, boolean toCamelCase) throws InstantiationException, IllegalAccessException,
InvocationTargetException {
T object = clazz.newInstance();
return toObject(object, map, toCamelCase);
}
/**
* 将Map转换为Object
* @param clazz 目标对象的类
* @param map 待转换Map
*/
public static <T, V> T toObject(T object, Map<String, V> map) throws InstantiationException, IllegalAccessException, InvocationTargetException {
return toObject(object, map, false);
}
/**
* 将Map转换为Object
* @param object 目标对象的类
* @param map 待转换Map
* @param toCamelCase 是否采用驼峰命名法转换
*/
public static <T, V> T toObject(T object, Map<String, V> map, boolean toCamelCase) throws InstantiationException, IllegalAccessException,
InvocationTargetException {
if (toCamelCase) {
map = toCamelCaseMap(map);
}
BeanUtils.populate(object, map);
return object;
}
/**
* 对象转Map
* @param object 目标对象
* @return 转换出来的值都是String
*/
public static Map<String, String> toMap(Object object) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return BeanUtils.describe(object);
}
/**
* 对象转Map
* @param object 目标对象
* @return 转换出来的值类型是原类型
*/
public static Map<String, Object> toNavMap(Object object) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
return PropertyUtils.describe(object);
}
/**
* 转换为Collection<Map<K, V>>
* @param collection 待转换对象集合
* @return 转换后的Collection<Map<K, V>>
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public static <T> Collection<Map<String, String>> toMapList(Collection<T> collection) throws IllegalAccessException, InvocationTargetException,
NoSuchMethodException {
List<Map<String, String>> retList = new ArrayList<Map<String, String>>();
if (collection != null && !collection.isEmpty()) {
for (Object object : collection) {
Map<String, String> map = toMap(object);
retList.add(map);
}
}
return retList;
}
/**
* 转换为Collection,同时为字段做驼峰转换<Map<K, V>>
* @param collection 待转换对象集合
* @return 转换后的Collection<Map<K, V>>
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public static <T> Collection<Map<String, String>> toMapListForFlat(Collection<T> collection) throws IllegalAccessException,
InvocationTargetException, NoSuchMethodException {
List<Map<String, String>> retList = new ArrayList<Map<String, String>>();
if (collection != null && !collection.isEmpty()) {
for (Object object : collection) {
Map<String, String> map = toMapForFlat(object);
retList.add(map);
}
}
return retList;
}
/**
* 转换成Map并提供字段命名驼峰转平行
* @param clazz 目标对象所在类
* @param object 目标对象
* @param map 待转换Map
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static Map<String, String> toMapForFlat(Object object) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Map<String, String> map = toMap(object);
return toUnderlineStringMap(map);
}
/**
* 将Map的Keys去下划线<br>
* (例:branch_no -> branchNo )<br>
* @param map 待转换Map
* @return
*/
public static <V> Map<String, V> toCamelCaseMap(Map<String, V> map) {
Map<String, V> newMap = new HashMap<String, V>();
for (String key : map.keySet()) {
safeAddToMap(newMap, StringUtils.camelCase(key), map.get(key));
}
return newMap;
}
/**
* 将Map的Keys转译成下划线格式的<br>
* (例:branchNo -> branch_no)<br>
* @param map 待转换Map
* @return
*/
public static <V> Map<String, V> toUnderlineStringMap(Map<String, V> map) {
Map<String, V> newMap = new HashMap<String, V>();
for (String key : map.keySet()) {
newMap.put(StringUtils.uncamelCase(key), map.get(key));
}
return newMap;
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.collect;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* Set工具类
* @author ThinkGem
* @version 2015-01-15
*/
public class SetUtils extends org.apache.commons.collections.SetUtils {
public static <E> HashSet<E> newHashSet() {
return new HashSet<E>();
}
@SafeVarargs
public static <E> HashSet<E> newHashSet(E... elements) {
HashSet<E> set = newHashSet(elements.length);
Collections.addAll(set, elements);
return set;
}
public static <E> HashSet<E> newHashSet(int initialCapacity) {
return new HashSet<E>(initialCapacity);
}
public static <E> HashSet<E> newHashSet(Iterable<? extends E> elements) {
return (elements instanceof Collection) ? new HashSet<E>(cast(elements)) : newHashSet(elements.iterator());
}
public static <E> HashSet<E> newHashSet(Iterator<? extends E> elements) {
HashSet<E> set = newHashSet();
addAll(set, elements);
return set;
}
public static <E> Set<E> newConcurrentHashSet() {
return Collections.newSetFromMap(new ConcurrentHashMap<E, Boolean>());
}
public static <E> Set<E> newConcurrentHashSet(Iterable<? extends E> elements) {
Set<E> set = newConcurrentHashSet();
addAll(set, elements);
return set;
}
public static <E> LinkedHashSet<E> newLinkedHashSet() {
return new LinkedHashSet<E>();
}
public static <E> LinkedHashSet<E> newLinkedHashSet(int initialCapacity) {
return new LinkedHashSet<E>(initialCapacity);
}
public static <E> LinkedHashSet<E> newLinkedHashSet(Iterable<? extends E> elements) {
if (elements instanceof Collection) {
return new LinkedHashSet<E>(cast(elements));
}
LinkedHashSet<E> set = newLinkedHashSet();
addAll(set, elements);
return set;
}
@SuppressWarnings("rawtypes")
public static <E extends Comparable> TreeSet<E> newTreeSet() {
return new TreeSet<E>();
}
@SuppressWarnings("rawtypes")
public static <E extends Comparable> TreeSet<E> newTreeSet(Iterable<? extends E> elements) {
TreeSet<E> set = newTreeSet();
addAll(set, elements);
return set;
}
public static <E> TreeSet<E> newTreeSet(Comparator<? super E> comparator) {
return new TreeSet<E>(comparator);
}
public static <E> Set<E> newIdentityHashSet() {
return Collections.newSetFromMap(MapUtils.<E, Boolean> newIdentityHashMap());
}
public static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet() {
return new CopyOnWriteArraySet<E>();
}
public static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(Iterable<? extends E> elements) {
Collection<? extends E> elementsCollection = (elements instanceof Collection) ? cast(elements) : ListUtils.newArrayList(elements);
return new CopyOnWriteArraySet<E>(elementsCollection);
}
private static <T> Collection<T> cast(Iterable<T> iterable) {
return (Collection<T>) iterable;
}
private static <T> boolean addAll(Collection<T> addTo, Iterator<? extends T> iterator) {
boolean wasModified = false;
while (iterator.hasNext()) {
wasModified |= addTo.add(iterator.next());
}
return wasModified;
}
public static <T> boolean addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
if (elementsToAdd instanceof Collection) {
Collection<? extends T> c = cast(elementsToAdd);
return addTo.addAll(c);
}
return addAll(addTo, elementsToAdd.iterator());
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.exec;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
/**
* Command
* @author ThinkGem
* @version 2017年2月17日
*/
public class CommandUtils {
public static String execute(String command) throws IOException {
return execute(command, "GBK");
}
public static String execute(String command, String charsetName) throws IOException {
Process process = Runtime.getRuntime().exec(command);
// 记录dos命令的返回信息
StringBuffer stringBuffer = new StringBuffer();
// 获取返回信息的流
InputStream in = process.getInputStream();
Reader reader = new InputStreamReader(in, charsetName);
BufferedReader bReader = new BufferedReader(reader);
String res = bReader.readLine();
while (res != null) {
stringBuffer.append(res);
stringBuffer.append("\n");
res = bReader.readLine();
}
bReader.close();
reader.close();
return stringBuffer.toString();
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.idgen;
import java.security.SecureRandom;
import java.util.UUID;
import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.lang.ObjectUtils;
import com.jeesite.common.lang.StringUtils;
/**
* 封装各种生成唯一性ID算法的工具类.
* @author ThinkGem
* @version 2014-8-19
*/
public class IdGenerate {
private static SecureRandom random = new SecureRandom();
private static IdWorker idWorker = new IdWorker(-1, -1);
/**
* 生成UUID, 中间无-分割.
*/
public static String uuid() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
/**
* 使用SecureRandom随机生成Long.
*/
public static long randomLong() {
return Math.abs(random.nextLong());
}
/**
* 基于Base62编码的SecureRandom随机生成bytes.
*/
public static String randomBase62(int length) {
byte[] randomBytes = new byte[length];
random.nextBytes(randomBytes);
return EncodeUtils.encodeBase62(randomBytes);
}
/**
* 获取新唯一编号(18为数值)
* 来自于twitter项目snowflake的id产生方案,全局唯一,时间有序。
* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
*/
public static String nextId() {
return String.valueOf(idWorker.nextId());
}
/**
* 获取新代码编号
*/
public static String nextCode(String code){
if (code != null){
String str = code.trim();
int len = str.length() - 1;
int lastNotNumIndex = 0;
for (int i = len; i >= 0; i--) {
if (!(str.charAt(i) >= '0' && str.charAt(i) <= '9')) {
lastNotNumIndex = i;
break;
}
}
// 如果最后一位是数字,并且last索引位置还在最后,则代表是纯数字,则最后一个不是数字的索引为-1
if ((str.charAt(len) >= '0' && str.charAt(len) <= '9') && (lastNotNumIndex == len)) {
lastNotNumIndex = -1;
}
String prefix = str.substring(0, lastNotNumIndex + 1);
String numStr = str.substring(lastNotNumIndex + 1, str.length());
long num = ObjectUtils.toLong(numStr);
// System.out.println("处理前:"+str);
str = prefix + StringUtils.leftPad(String.valueOf(num + 1), numStr.length(), "0");
// System.out.println("处理后:"+str);
return str;
}
return null;
}
// public static void main(String[] args) {
// System.out.println(uuid());
// System.out.println(nextId());
// System.out.println(nextCode("8"));
// System.out.println(nextCode("09"));
// System.out.println(nextCode("009"));
// System.out.println(nextCode("E09"));
// System.out.println(nextCode("EC09"));
// System.out.println(nextCode("EC0101"));
// System.out.println(nextCode("EC0109"));
// System.out.println(nextCode("EC02T03"));
// System.out.println(nextCode("EC02T099"));
// System.out.println(nextCode("EC02T100"));
// System.out.println(nextCode("EC02T10A"));
//// // 数值型ID重复验证测试
//// Set<String> set = SetUtils.newHashSet();
//// try{
//// for (int i=0; i<100; i++){
//// String id = String.valueOf(nextId());
//// if (set.contains(id)){
//// throw new Exception(id + " exists");
//// }
//// set.add(id);
//// System.out.println(id);
//// Thread.sleep(100);
//// }
//// }catch (Exception e) {
//// e.printStackTrace();
//// }
// }
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.idgen;
import java.util.Random;
/**
* 来自于twitter项目snowflake的id产生方案,全局唯一,时间有序。
* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
* https://github.com/twitter/snowflake/blob/scala_28/src/main/
* scala/com/twitter/service/snowflake/IdWorker.scala
*/
public class IdWorker {
private final static long twepoch = 1288834974657L;
// 机器标识位数
private final static long workerIdBits = 5L;
// 数据中心标识位数
private final static long datacenterIdBits = 5L;
// 机器ID最大值
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
// 数据中心ID最大值
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
// 毫秒内自增位
private final static long sequenceBits = 12L;
// 机器ID偏左移12位
private final static long workerIdShift = sequenceBits;
// 数据中心ID左移17位
private final static long datacenterIdShift = sequenceBits + workerIdBits;
// 时间毫秒左移22位
private final static long timestampLeftShift = sequenceBits + workerIdBits
+ datacenterIdBits;
private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
private static long lastTimestamp = -1L;
private long sequence = 0L;
private final long workerId;
private final long datacenterId;
public IdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
if (workerId == -1){
this.workerId = new Random().nextInt((int)maxWorkerId);
}else{
throw new IllegalArgumentException(
"worker Id can't be greater than %d or less than 0");
}
}else{
this.workerId = workerId;
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
if (datacenterId == -1){
this.datacenterId = new Random().nextInt((int)maxDatacenterId);
}else{
throw new IllegalArgumentException(
"datacenter Id can't be greater than %d or less than 0");
}
}else{
this.datacenterId = datacenterId;
}
}
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
try {
throw new Exception(
"Clock moved backwards. Refusing to generate id for "
+ (lastTimestamp - timestamp) + " milliseconds");
} catch (Exception e) {
e.printStackTrace();
}
}
if (lastTimestamp == timestamp) {
// 当前毫秒内,则+1
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 当前毫秒内计数满了,则等待下一秒
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
lastTimestamp = timestamp;
// ID偏移组合生成最终的ID,并返回ID
long nextId = ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift) | sequence;
return nextId;
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
// //////////// test ////////////
//
// public static void main(String[] args) throws Exception {
// final Set<Long> set = SetUtils.newHashSet();
//
// final IdWorker w1 = new IdWorker(-1, -1);
// final IdWorker w2 = new IdWorker(-1, -1);
// final CyclicBarrier cdl = new CyclicBarrier(100);
//
// for (int i = 0; i < 1000; i++) {
// new Thread(new Runnable() {
// @Override
// public void run() {
// try {
// cdl.await();
// } catch (InterruptedException e) {
// e.printStackTrace();
// } catch (BrokenBarrierException e) {
// e.printStackTrace();
// }
//
// // id
// Long id = w1.nextId();
// if (set.contains(id)){
// System.out.println(id + " exists");
// }
// set.add(id);
// System.out.println(id);
//
// // id2
// Long id2 = w2.nextId();
// if (set.contains(id2)){
// System.out.println(id2 + " exists");
// }
// set.add(id2);
// System.out.println(id2);
// }
// }).start();
// }
// try {
// TimeUnit.SECONDS.sleep(5);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
}
\ No newline at end of file
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.image;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import org.patchca.background.BackgroundFactory;
import org.patchca.color.ColorFactory;
import org.patchca.filter.predefined.CurvesRippleFilterFactory;
import org.patchca.filter.predefined.DiffuseRippleFilterFactory;
import org.patchca.filter.predefined.DoubleRippleFilterFactory;
import org.patchca.filter.predefined.MarbleRippleFilterFactory;
import org.patchca.filter.predefined.WobbleRippleFilterFactory;
import org.patchca.font.RandomFontFactory;
import org.patchca.service.ConfigurableCaptchaService;
import org.patchca.text.renderer.BestFitTextRenderer;
import org.patchca.utils.encoder.EncoderHelper;
import org.patchca.word.RandomWordFactory;
/**
* 验证码工具
* @author ThinkGem
* @version 2017年12月23日
*/
public class CaptchaUtils {
private static Random random = new Random();
private static ConfigurableCaptchaService ccs;
private static WobbleRippleFilterFactory wrff; // 摆波纹
private static DoubleRippleFilterFactory doff; // 双波纹
private static CurvesRippleFilterFactory crff; // 曲线波纹
private static DiffuseRippleFilterFactory drff; // 漫纹波
private static MarbleRippleFilterFactory mrff; // 大理石
private static void initialize(){
if (ccs == null){
synchronized (CaptchaUtils.class) {
if (ccs == null){
// 配置初始化
ccs = new ConfigurableCaptchaService();
// 设置图片大小
ccs.setWidth(100);
ccs.setHeight(28);
// 设置文字数量
RandomWordFactory wf = new RandomWordFactory();
wf.setCharacters("ABDEFGHKMNRSWX2345689");
wf.setMinLength(4);
wf.setMaxLength(4);
ccs.setWordFactory(wf);
// 设置字体大小
RandomFontFactory ff = new RandomFontFactory();
ff.setMinSize(28);
ff.setMaxSize(28);
ccs.setFontFactory(ff);
// 设置文字渲染边距
BestFitTextRenderer tr = new BestFitTextRenderer();
tr.setTopMargin(3);
tr.setRightMargin(3);
tr.setBottomMargin(3);
tr.setLeftMargin(3);
ccs.setTextRenderer(tr);
// 设置字体颜色
ccs.setColorFactory(new ColorFactory() {
@Override
public Color getColor(int x) {
int r = random.nextInt(90);
int g = random.nextInt(90);
int b = random.nextInt(90);
return new Color(r, g, b);
}
});
// 设置背景
ccs.setBackgroundFactory(new BackgroundFactory() {
@Override
public void fillBackground(BufferedImage image) {
Graphics graphics = image.getGraphics();
// 验证码图片的宽高
int imgWidth = image.getWidth();
int imgHeight = image.getHeight();
// 填充为白色背景
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, imgWidth, imgHeight);
// 画 50 个噪点(颜色及位置随机)
for (int i = 0; i < 50; i++) {
// 随机颜色
int rInt = random.nextInt(100)+50;
int gInt = random.nextInt(100)+50;
int bInt = random.nextInt(100)+50;
graphics.setColor(new Color(rInt, gInt, bInt));
// 随机位置
int xInt = random.nextInt(imgWidth - 3);
int yInt = random.nextInt(imgHeight - 2);
// 随机旋转角度
int sAngleInt = random.nextInt(360);
int eAngleInt = random.nextInt(360);
// 随机大小
int wInt = random.nextInt(6);
int hInt = random.nextInt(6);
// 填充背景
graphics.fillArc(xInt, yInt, wInt, hInt, sAngleInt, eAngleInt);
// 画5条干扰线
if (i % 10 == 0) {
int xInt2 = random.nextInt(imgWidth);
int yInt2 = random.nextInt(imgHeight);
graphics.drawLine(xInt, yInt, xInt2, yInt2);
}
}
}
});
// 效果初始化
wrff = new WobbleRippleFilterFactory(); // 摆波纹
doff = new DoubleRippleFilterFactory(); // 双波纹
crff = new CurvesRippleFilterFactory(ccs.getColorFactory()); // 曲线波纹
drff = new DiffuseRippleFilterFactory(); // 漫纹波
mrff = new MarbleRippleFilterFactory(); // 大理石
}
}
}
}
/**
* 生成验证码
* @param request
* @param response
* @throws IOException
* @return 验证码字符
*/
public static String generateCaptcha(OutputStream outputStream) throws IOException{
// 初始化设置
initialize();
// 随机选择一个样式
switch (random.nextInt(3)) {
case 0:
ccs.setFilterFactory(wrff); // 摆波纹
break;
case 1:
ccs.setFilterFactory(doff); // 双波纹
break;
case 2:
ccs.setFilterFactory(crff); // 曲线波纹
break;
case 3:
ccs.setFilterFactory(drff); // 漫纹波
break;
case 4:
ccs.setFilterFactory(mrff); // 大理石
break;
}
// 生成验证码
String s = EncoderHelper.getChallangeAndWriteImage(ccs, "png", outputStream);
// System.out.println(s);
return s;
}
// public static void main(String[] args) throws IOException {
//
// FileOutputStream fos = new FileOutputStream("x:\\captcha.png");
// String s = generateCaptcha(fos);
// System.out.println(s);
// fos.close();
//
// }
}
///**
// * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
// */
//package com.jeesite.common.image;
//
//import java.io.File;
//
//import com.drew.imaging.jpeg.JpegMetadataReader;
//import com.drew.lang.Rational;
//import com.drew.metadata.Metadata;
//import com.drew.metadata.exif.GpsDirectory;
//
///**
// * 图片地理信息获取
// * @author ThinkGem
// */
//public class ImageGeo {
//
// public double lat = 0.0;
// public double lon = 0.0;
// public double alt = 0.0;
// public boolean error = false;
//
// public ImageGeo(String filename) {
// try {
// error = false;
// File jpegFile = new File(filename);
// Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);
//
// GpsDirectory gpsdir = (GpsDirectory) metadata.getDirectoriesOfType(GpsDirectory.class);
// Rational latpart[] = gpsdir.getRationalArray(GpsDirectory.TAG_LATITUDE);
// Rational lonpart[] = gpsdir.getRationalArray(GpsDirectory.TAG_LONGITUDE);
// String northing = gpsdir.getString(GpsDirectory.TAG_LATITUDE_REF);
// String easting = gpsdir.getString(GpsDirectory.TAG_LONGITUDE_REF);
//
// try {
// alt = gpsdir.getDouble(GpsDirectory.TAG_ALTITUDE);
// } catch (Exception ex) {}
//
// double latsign = 1.0d;
// if (northing.equalsIgnoreCase("S")) {
// latsign = -1.0d;
// }
// double lonsign = 1.0d;
// if (easting.equalsIgnoreCase("W")) {
// lonsign = -1.0d;
// }
//
// lat = (Math.abs(latpart[0].doubleValue()) + latpart[1].doubleValue() / 60.0d + latpart[2].doubleValue() / 3600.0d) * latsign;
// lon = (Math.abs(lonpart[0].doubleValue()) + lonpart[1].doubleValue() / 60.0d + lonpart[2].doubleValue() / 3600.0d) * lonsign;
//
// if (Double.isNaN(lat) || Double.isNaN(lon)) {
// error = true;
// }
// } catch (Exception ex) {
// error = true;
// }
// System.out.println(filename + ": (" + lat + ", " + lon + ")");
// }
//
//// public static void main(String[] args) {
//// ImageGeo imageGeo = new ImageGeo(ImageGeo.class.getResource("IMAG0068.jpg").getFile());
//// System.out.println(imageGeo.lon + "," + imageGeo.lat);
//// }
//
//}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jeesite.common.io.FileUtils;
import com.jeesite.common.lang.StringUtils;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;
/**
* 图片处理工具类
* @author ThinkGem
* @version 2018年12月31日
*/
public class ImageUtils {
private static Logger logger = LoggerFactory.getLogger(ImageUtils.class);
/**
* 缩略图生成,处理一些较大的图片,防止占用太多的网络资源
*/
public static void thumbnails(File imageFile, int maxWidth, int maxHeight, String outputFormat){
if (imageFile == null || !imageFile.exists() || (maxWidth <= 0 && maxHeight <= 0)){
return;
}
// 只处理可以压缩的图片,如gif图片压缩后会出现黑色背景的情况
String extension = FileUtils.getFileExtension(imageFile.getName());
if (!StringUtils.inString(extension, "png", "jpg", "jpeg", "bmp", "ico")){
return;
}
try{
BufferedImage bufferedImage = ImageIO.read(imageFile);
Builder<BufferedImage> bilder = Thumbnails.of(bufferedImage);
if (bufferedImage != null){
if (maxWidth > 0){
if (bufferedImage.getWidth() <= maxWidth){
bilder.width(bufferedImage.getWidth());
}else{
bilder.width(maxWidth);
}
}
if (maxHeight > 0){
if (bufferedImage.getHeight() <= maxHeight){
bilder.height(bufferedImage.getHeight());
}else{
bilder.height(maxHeight);
}
}
if (StringUtils.isNotBlank(outputFormat)){
bilder.outputFormat(outputFormat);
}
bilder.toFile(imageFile);
}
}catch(IOException e){
logger.error("图片压缩失败:" + imageFile.getAbsoluteFile(), e);
}
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Hashtable;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
/**
* 条形码和二维码编码解码
* @author ThinkGem
* @version 2014-02-28
*/
public class ZxingUtils {
/**
* 条形码编码
*
* @param contents
* @param width
* @param height
* @param imgPath
*/
public static void encode(String contents, int width, int height, String imgPath) {
int codeWidth = 3 + // start guard
(7 * 6) + // left bars
5 + // middle guard
(7 * 6) + // right bars
3; // end guard
codeWidth = Math.max(codeWidth, width);
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.EAN_13, codeWidth, height, null);
MatrixToImageWriter.writeToPath(bitMatrix, "png", new File(imgPath).toPath());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 条形码解码
*
* @param imgPath
* @return String
*/
public static String decode(String imgPath) {
BufferedImage image = null;
Result result = null;
try {
image = ImageIO.read(new File(imgPath));
if (image == null) {
System.out.println("the decode image may be not exit.");
}
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
result = new MultiFormatReader().decode(bitmap, null);
return result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 二维码编码
*
* @param contents
* @param width
* @param height
* @param imgPath
*/
public static void encode2(String contents, int width, int height, String imgPath) {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
// 指定纠错等级
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
// 指定编码格式
hints.put(EncodeHintType.CHARACTER_SET, "GBK");
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);
MatrixToImageWriter.writeToPath(bitMatrix, "png", new File(imgPath).toPath());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 二维码解码
*
* @param imgPath
* @return String
*/
public static String decode2(String imgPath) {
BufferedImage image = null;
Result result = null;
try {
image = ImageIO.read(new File(imgPath));
if (image == null) {
System.out.println("the decode image may be not exit.");
}
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "GBK");
result = new MultiFormatReader().decode(bitmap, hints);
return result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// public static void main(String[] args) {
//
// // 条形码
// String imgPath = "target\\zxing_EAN13.png";
// String contents = "6923450657713";
// int width = 105, height = 50;
//
// ZxingUtils.encode(contents, width, height, imgPath);
// System.out.println("finished zxing EAN-13 encode.");
//
// String decodeContent = ZxingUtils.decode(imgPath);
// System.out.println("解码内容如下:" + decodeContent);
// System.out.println("finished zxing EAN-13 decode.");
//
// // 二维码
// String imgPath2 = "target\\zxing.png";
// String contents2 = "Hello Gem, welcome to Zxing!" + "\nBlog [ http://thinkgem.iteye.com ]" + "\nEMail [ thinkgem@163.com ]";
// int width2 = 300, height2 = 300;
//
// ZxingUtils.encode2(contents2, width2, height2, imgPath2);
// System.out.println("finished zxing encode.");
//
// String decodeContent2 = ZxingUtils.decode2(imgPath2);
// System.out.println("解码内容如下:" + decodeContent2);
// System.out.println("finished zxing decode.");
//
// }
}
\ No newline at end of file
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.io;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 数据流工具类
* @author ThinkGem
*/
public class IOUtils extends org.apache.commons.io.IOUtils {
/**
* 根据文件路径创建文件输入流处理 以字节为单位(非 unicode )
* @param path
* @return
*/
public static FileInputStream getFileInputStream(String filepath) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(filepath);
} catch (FileNotFoundException e) {
System.out.println("错误信息:文件不存在");
e.printStackTrace();
}
return fileInputStream;
}
/**
* 根据文件对象创建文件输入流处理 以字节为单位(非 unicode )
* @param path
* @return
*/
public static FileInputStream getFileInputStream(File file) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
System.out.println("错误信息:文件不存在");
e.printStackTrace();
}
return fileInputStream;
}
/**
* 根据文件对象创建文件输出流处理 以字节为单位(非 unicode )
* @param file
* @param append true:文件以追加方式打开,false:则覆盖原文件的内容
* @return
*/
public static FileOutputStream getFileOutputStream(File file, boolean append) {
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(file, append);
} catch (FileNotFoundException e) {
System.out.println("错误信息:文件不存在");
e.printStackTrace();
}
return fileOutputStream;
}
/**
* 根据文件路径创建文件输出流处理 以字节为单位(非 unicode )
* @param path
* @param append true:文件以追加方式打开,false:则覆盖原文件的内容
* @return
*/
public static FileOutputStream getFileOutputStream(String filepath, boolean append) {
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filepath, append);
} catch (FileNotFoundException e) {
System.out.println("错误信息:文件不存在");
e.printStackTrace();
}
return fileOutputStream;
}
/**
* Closes a <code>Closeable</code> unconditionally.
*/
public static void closeQuietly(final InputStream input) {
closeQuietly((Closeable) input);
}
/**
* Closes a <code>Closeable</code> unconditionally.
*/
public static void closeQuietly(final Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (final IOException ioe) {
// ignore
}
}
}
\ No newline at end of file
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.io;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import com.jeesite.common.collect.SetUtils;
import com.jeesite.common.lang.ObjectUtils;
import com.jeesite.common.lang.StringUtils;
/**
* Properties工具类, 可载入多个properties、yml文件,
* 相同的属性在最后载入的文件中的值将会覆盖之前的值,
* 取不到从System.getProperty()获取。
* @author ThinkGem
* @version 2017-12-30
*/
public class PropertiesUtils {
// 默认加载的文件,可通过继承覆盖(若有相同Key,优先加载后面的)
public static final String[] DEFAULT_CONFIG_FILE = new String[]{
"classpath:config/bootstrap.yml", "classpath:bootstrap.yml",
"classpath:config/application.yml", "classpath:application.yml"};
private static Logger logger = PropertiesUtils.initLogger();
private final Set<String> configSet = SetUtils.newLinkedHashSet();
private final Properties properties = new Properties();
private static Environment environment;
/**
* 当前类的实例持有者(静态内部类,延迟加载,懒汉式,线程安全的单例模式)
*/
private static final class PropertiesLoaderHolder {
private static PropertiesUtils INSTANCE;
static {
releadInstance();
}
public static void releadInstance(){
// 获取平台及模块相关的配置文件
Set<String> configSet = SetUtils.newLinkedHashSet();
Resource[] resources = ResourceUtils.getResources("classpath*:/config/jeesite-*.*");
for(Resource resource : resources){
configSet.add("classpath:config/"+resource.getFilename());
}
//configSet.add("classpath:config/jeesite.yml");
// 获取全局设置默认的配置文件(以下是支持环境配置的属性文件)
Set<String> set = SetUtils.newLinkedHashSet();
for (String configFile : DEFAULT_CONFIG_FILE){
set.add(configFile);
}
// 获取 spring.config.location 外部自定义的配置文件
String customConfigs = System.getProperty("spring.config.location");
if (StringUtils.isNotBlank(customConfigs)){
for (String customConfig : StringUtils.split(customConfigs, ",")){
if (!customConfig.contains("$")){
customConfig = org.springframework.util.StringUtils.cleanPath(customConfig);
if (!ResourceUtils.isUrl(customConfig)){
customConfig = ResourceUtils.FILE_URL_PREFIX + customConfig;
}
}
set.add(customConfig);
}
}
// 获取 spring.profiles.active 活动环境名称的配置文件
String[] configFiles = set.toArray(new String[set.size()]);
String profiles = System.getProperty("spring.profiles.active");
if (StringUtils.isBlank(profiles)){
PropertiesUtils propsTemp = new PropertiesUtils(configFiles);
profiles = propsTemp.getProperty("spring.profiles.active");
}
for (String location : configFiles){
configSet.add(location);
if (StringUtils.isNotBlank(profiles)){
if (location.endsWith(".properties")){
configSet.add(StringUtils.substringBeforeLast(location, ".properties")
+ "-" + profiles + ".properties");
}else if (location.endsWith(".yml")){
configSet.add(StringUtils.substringBeforeLast(location, ".yml")
+ "-" + profiles + ".yml");
}
}
}
configFiles = configSet.toArray(new String[configSet.size()]);
logger.debug("Loading jeesite config: {}", (Object)configFiles);
INSTANCE = new PropertiesUtils(configFiles);
}
}
/**
* 载入多个文件,路径使用Spring Resource格式,相同的属性在最后载入的文件中的值将会覆盖之前的值。
*/
public PropertiesUtils(String... configFiles) {
for (String location : configFiles) {
try {
Resource resource = ResourceUtils.getResource(location);
if (resource.exists()){
if (location.endsWith(".properties")){
try (InputStreamReader is = new InputStreamReader(resource.getInputStream(), "UTF-8")){
properties.load(is);
configSet.add(location);
} catch (IOException ex) {
logger.error("Load " + location + " failure. ", ex);
}
}
else if (location.endsWith(".yml")){
YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean();
bean.setResources(resource);
for (Map.Entry<Object,Object> entry : bean.getObject().entrySet()){
properties.put(ObjectUtils.toString(entry.getKey()),
ObjectUtils.toString(entry.getValue()));
}
configSet.add(location);
}
}
} catch (Exception e) {
logger.error("Load " + location + " failure. ", e);
}
}
}
/**
* 获取当前加载的属性文件
*/
public Set<String> getConfigSet() {
return configSet;
}
/**
* 获取当前加载的属性数据
*/
public Properties getProperties() {
return properties;
}
/**
* 当前类实例
*/
public static PropertiesUtils getInstance(){
return PropertiesLoaderHolder.INSTANCE;
}
/**
* 重新加载实例(重新实例化,以重新加载属性文件数据)
*/
public static void releadInstance(){
PropertiesLoaderHolder.releadInstance();
}
// 正则表达式预编译
private static Pattern p1 = Pattern.compile("\\$\\{.*?\\}");
/**
* 获取属性值,取不到从System.getProperty()获取,都取不到返回null
*/
public String getProperty(String key) {
if (environment != null){
String value = environment.getProperty(key);
if (value != null){
return value;
}
}
String value = properties.getProperty(key);
if (value != null){
Matcher m = p1.matcher(value);
while(m.find()) {
String g = m.group();
String childKey = g.replaceAll("\\$\\{|\\}", "");
value = StringUtils.replace(value, g, getProperty(childKey));
}
return value;
}else{
String systemProperty = System.getProperty(key);
if (systemProperty != null) {
return systemProperty;
}
}
return null;
}
/**
* 取出String类型的Property,但以System的Property优先,如果都为null则返回defaultValue值
*/
public String getProperty(String key, String defaultValue) {
String value = getProperty(key);
return value != null ? value : defaultValue;
}
/**
* 设置环境属性
* @param environment
*/
public static void setEnvironment(Environment environment) {
PropertiesUtils.environment = environment;
}
/**
* 初始化日志路径
*/
private static Logger initLogger(){
String logPath = null;
try {
// 获取当前classes目录
logPath = ResourceUtils.getResource("/").getFile().getPath();
} catch (Exception e) {
// 取不到,取当前工作路径
logPath = System.getProperty("user.dir");
}
// 取当前日志路径下有classes目录,则使用classes目录
String classesLogPath = FileUtils.path(logPath + "/WEB-INF/classes");
if (new File(classesLogPath).exists()){
logPath = classesLogPath;
}
if (StringUtils.isBlank(System.getProperty("logPath"))){
System.setProperty("logPath", FileUtils.path(logPath));
}
return LoggerFactory.getLogger(PropertiesUtils.class);
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.io;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
/**
* 配置文件加载(Boot)
* @author ThinkGem
* @version 2018-10-16
*/
public class PropertyLoader implements org.springframework.boot.env.PropertySourceLoader{
private static boolean isLoadPropertySource = false;
@Override
public String[] getFileExtensions() {
return new String[] { "properties", "yml" };
}
@Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
if (!isLoadPropertySource){
isLoadPropertySource = true;
Properties properties = PropertiesUtils.getInstance().getProperties();
return Collections.singletonList(new OriginTrackedMapPropertySource("jeesite", properties));
}
return Collections.emptyList();
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.io;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import com.jeesite.common.lang.ExceptionUtils;
/**
* 资源供给类
* @author ThinkGem
* @version 2016-9-16
*/
public class ResourceUtils extends org.springframework.util.ResourceUtils {
private static ResourceLoader resourceLoader;
private static ResourcePatternResolver resourceResolver;
static{
resourceLoader = new DefaultResourceLoader();
resourceResolver = new PathMatchingResourcePatternResolver(resourceLoader);
}
/**
* 获取资源加载器(可读取jar内的文件)
* @author ThinkGem
*/
public static ResourceLoader getResourceLoader() {
return resourceLoader;
}
/**
* 获取ClassLoader
*/
public static ClassLoader getClassLoader() {
return resourceLoader.getClassLoader();
}
/**
* 获取资源加载器(可读取jar内的文件)
*/
public static Resource getResource(String location) {
return resourceLoader.getResource(location);
}
/**
* 获取资源文件流(用后记得关闭)
* @param location
* @author ThinkGem
* @throws IOException
*/
public static InputStream getResourceFileStream(String location) throws IOException{
Resource resource = resourceLoader.getResource(location);
return resource.getInputStream();
}
/**
* 获取资源文件内容
* @param location
* @author ThinkGem
*/
public static String getResourceFileContent(String location){
try(InputStream is = ResourceUtils.getResourceFileStream(location)){
return IOUtils.toString(is, "UTF-8");
}catch (IOException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* Spring 搜索资源文件
* @param locationPattern
* @author ThinkGem
*/
public static Resource[] getResources(String locationPattern){
try {
Resource[] resources = resourceResolver.getResources(locationPattern);
return resources;
} catch (IOException e) {
throw ExceptionUtils.unchecked(e);
}
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.lang;
/**
* 字节转换工具
* @author ThinkGem
* @version 2015-6-20
*/
public class ByteUtils {
private static final int UNIT = 1024;
/**
* @param byteSize 字节
* @return
*/
public static String formatByteSize(long byteSize) {
if (byteSize <= -1){
return String.valueOf(byteSize);
}
double size = 1.0 * byteSize;
String type = "B";
if((int)Math.floor(size / UNIT) <= 0) { //不足1KB
type = "B";
return format(size, type);
}
size = size / UNIT;
if((int)Math.floor(size / UNIT) <= 0) { //不足1MB
type = "KB";
return format(size, type);
}
size = size / UNIT;
if((int)Math.floor(size / UNIT) <= 0) { //不足1GB
type = "MB";
return format(size, type);
}
size = size / UNIT;
if((int)Math.floor(size / UNIT) <= 0) { //不足1TB
type = "GB";
return format(size, type);
}
size = size / UNIT;
if((int)Math.floor(size / UNIT) <= 0) { //不足1PB
type = "TB";
return format(size, type);
}
size = size / UNIT;
if((int)Math.floor(size / UNIT) <= 0) {
type = "PB";
return format(size, type);
}
return ">PB";
}
private static String format(double size, String type) {
int precision = 0;
if(size * 1000 % 10 > 0) {
precision = 3;
} else if(size * 100 % 10 > 0) {
precision = 2;
} else if(size * 10 % 10 > 0) {
precision = 1;
} else {
precision = 0;
}
String formatStr = "%." + precision + "f";
if("KB".equals(type)) {
return String.format(formatStr, (size)) + "KB";
} else if("MB".equals(type)) {
return String.format(formatStr, (size)) + "MB";
} else if("GB".equals(type)) {
return String.format(formatStr, (size)) + "GB";
} else if("TB".equals(type)) {
return String.format(formatStr, (size)) + "TB";
} else if("PB".equals(type)) {
return String.format(formatStr, (size)) + "PB";
}
return String.format(formatStr, (size)) + "B";
}
// public static void main(String[] args) {
// System.out.println(ByteUtils.formatByteSize(1023));
// System.out.println(ByteUtils.formatByteSize(1L * UNIT));
// System.out.println(ByteUtils.formatByteSize(1L * UNIT * UNIT));
// System.out.println(ByteUtils.formatByteSize(1L * UNIT * 1023));
// System.out.println(ByteUtils.formatByteSize(1L * 1023 * 1023 * 1023));
// System.out.println(ByteUtils.formatByteSize(1L * UNIT * UNIT * UNIT));
// System.out.println(ByteUtils.formatByteSize(1L * UNIT * UNIT * UNIT * UNIT));
// System.out.println(ByteUtils.formatByteSize(1L * UNIT * UNIT * UNIT * UNIT * UNIT));
// System.out.println(ByteUtils.formatByteSize(1L * UNIT * UNIT * UNIT * UNIT * UNIT * UNIT));
// }
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.lang;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
/**
* 日期工具类, 继承org.apache.commons.lang.time.DateUtils类
* @author ThinkGem
* @version 2017-1-4
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
private static String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH", "yyyy.MM",
"yyyy年MM月dd日", "yyyy年MM月dd日 HH时mm分ss秒", "yyyy年MM月dd日 HH时mm分", "yyyy年MM月dd日 HH时", "yyyy年MM月",
"yyyy"};
/**
* 得到日期字符串 ,转换格式(yyyy-MM-dd)
*/
public static String formatDate(Date date) {
return formatDate(date, "yyyy-MM-dd");
}
/**
* 得到日期字符串 默认格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E"
*/
public static String formatDate(long dateTime, String pattern) {
return formatDate(new Date(dateTime), pattern);
}
/**
* 得到日期字符串 默认格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E"
*/
public static String formatDate(Date date, String pattern) {
String formatDate = null;
if (date != null){
// if (StringUtils.isNotBlank(pattern)) {
// formatDate = DateFormatUtils.format(date, pattern);
// } else {
// formatDate = DateFormatUtils.format(date, "yyyy-MM-dd");
// }
if (StringUtils.isBlank(pattern)) {
pattern = "yyyy-MM-dd";
}
formatDate = FastDateFormat.getInstance(pattern).format(date);
}
return formatDate;
}
/**
* 得到日期时间字符串,转换格式(yyyy-MM-dd HH:mm:ss)
*/
public static String formatDateTime(Date date) {
return formatDate(date, "yyyy-MM-dd HH:mm:ss");
}
/**
* 得到当前日期字符串 格式(yyyy-MM-dd)
*/
public static String getDate() {
return getDate("yyyy-MM-dd");
}
/**
* 得到当前日期字符串 格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E"
*/
public static String getDate(String pattern) {
// return DateFormatUtils.format(new Date(), pattern);
return FastDateFormat.getInstance(pattern).format(new Date());
}
/**
* 得到当前日期前后多少天,月,年的日期字符串
* @param pattern 格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E"
* @param amont 数量,前为负数,后为正数
* @param type 类型,可参考Calendar的常量(如:Calendar.HOUR、Calendar.MINUTE、Calendar.SECOND)
* @return
*/
public static String getDate(String pattern, int amont, int type) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(type, amont);
// return DateFormatUtils.format(calendar.getTime(), pattern);
return FastDateFormat.getInstance(pattern).format(calendar.getTime());
}
/**
* 得到当前时间字符串 格式(HH:mm:ss)
*/
public static String getTime() {
return formatDate(new Date(), "HH:mm:ss");
}
/**
* 得到当前日期和时间字符串 格式(yyyy-MM-dd HH:mm:ss)
*/
public static String getDateTime() {
return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
}
/**
* 得到当前年份字符串 格式(yyyy)
*/
public static String getYear() {
return formatDate(new Date(), "yyyy");
}
/**
* 得到当前月份字符串 格式(MM)
*/
public static String getMonth() {
return formatDate(new Date(), "MM");
}
/**
* 得到当天字符串 格式(dd)
*/
public static String getDay() {
return formatDate(new Date(), "dd");
}
/**
* 得到当前星期字符串 格式(E)星期几
*/
public static String getWeek() {
return formatDate(new Date(), "E");
}
/**
* 日期型字符串转化为日期 格式 see to DateUtils#parsePatterns
*/
public static Date parseDate(Object str) {
if (str == null){
return null;
}
try {
return parseDate(str.toString(), parsePatterns);
} catch (ParseException e) {
return null;
}
}
/**
* 获取过去的天数
* @param date
* @return
*/
public static long pastDays(Date date) {
long t = System.currentTimeMillis()-date.getTime();
return t/(24*60*60*1000);
}
/**
* 获取过去的小时
* @param date
* @return
*/
public static long pastHour(Date date) {
long t = System.currentTimeMillis()-date.getTime();
return t/(60*60*1000);
}
/**
* 获取过去的分钟
* @param date
* @return
*/
public static long pastMinutes(Date date) {
long t = System.currentTimeMillis()-date.getTime();
return t/(60*1000);
}
/**
* 获取两个日期之间的天数
*
* @param before
* @param after
* @return
*/
public static double getDistanceOfTwoDate(Date before, Date after) {
long beforeTime = before.getTime();
long afterTime = after.getTime();
return (afterTime - beforeTime) / (1000 * 60 * 60 * 24);
}
/**
* 获取某月有几天
* @param date 日期
* @return 天数
*/
public static int getMonthHasDays(Date date){
// String yyyyMM = new SimpleDateFormat("yyyyMM").format(date);
String yyyyMM = FastDateFormat.getInstance("yyyyMM").format(date);
String year = yyyyMM.substring(0, 4);
String month = yyyyMM.substring(4, 6);
String day31 = ",01,03,05,07,08,10,12,";
String day30 = "04,06,09,11";
int day = 0;
if (day31.contains(month)) {
day = 31;
} else if (day30.contains(month)) {
day = 30;
} else {
int y = Integer.parseInt(year);
if ((y % 4 == 0 && (y % 100 != 0)) || y % 400 == 0) {
day = 29;
} else {
day = 28;
}
}
return day;
}
/**
* 获取日期是当年的第几周
* @param date
* @return
*/
public static int getWeekOfYear(Date date){
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal.get(Calendar.WEEK_OF_YEAR);
}
/**
* 获取一天的开始时间(如:2015-11-3 00:00:00.000)
* @param date 日期
* @return
*/
public static Date getOfDayFirst(Date date) {
if (date == null){
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
/**
* 获取一天的最后时间(如:2015-11-3 23:59:59.999)
* @param date 日期
* @return
*/
public static Date getOfDayLast(Date date) {
if (date == null){
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
return calendar.getTime();
}
/**
* 获取服务器启动时间
* @param date
* @return
*/
public static Date getServerStartDate(){
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time);
}
/**
* 格式化为日期范围字符串
* @param beginDate 2018-01-01
* @param endDate 2018-01-31
* @return 2018-01-01 ~ 2018-01-31
* @author ThinkGem
*/
public static String formatDateBetweenString(Date beginDate, Date endDate){
String begin = DateUtils.formatDate(beginDate);
String end = DateUtils.formatDate(endDate);
if (StringUtils.isNoneBlank(begin, end)){
return begin + " ~ " + end;
}
return null;
}
/**
* 解析日期范围字符串为日期对象
* @param dateString 2018-01-01 ~ 2018-01-31
* @return new Date[]{2018-01-01, 2018-01-31}
* @author ThinkGem
*/
public static Date[] parseDateBetweenString(String dateString){
Date beginDate = null; Date endDate = null;
if (StringUtils.isNotBlank(dateString)){
String[] ss = StringUtils.split(dateString, "~");
if (ss != null && ss.length == 2){
String begin = StringUtils.trim(ss[0]);
String end = StringUtils.trim(ss[1]);
if (StringUtils.isNoneBlank(begin, end)){
beginDate = DateUtils.parseDate(begin);
endDate = DateUtils.parseDate(end);
}
}
}
return new Date[]{beginDate, endDate};
}
// public static void main(String[] args) throws ParseException {
// System.out.println(formatDate(parseDate("2010/3/6")));
// System.out.println(getDate("yyyy年MM月dd日 E"));
// long time = new Date().getTime()-parseDate("2012-11-19").getTime();
// System.out.println(time/(24*60*60*1000));
// System.out.println(getWeekOfYear(new Date()));
// System.out.println(formatDate(getOfDayFirst(parseDate("2015/3/6")),"yyyy-MM-dd HH:mm:ss.sss"));
// System.out.println(formatDate(getOfDayLast(parseDate("2015/6/6")),"yyyy-MM-dd HH:mm:ss.sss"));
// }
}
/**
* Copyright (c) 2005-2012 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package com.jeesite.common.lang;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
/**
* 关于异常的工具类.
* @author calvin
* @version 2014-8-19
*/
public class ExceptionUtils {
/**
* 在request中获取异常类
* @param request
* @return
*/
public static Throwable getThrowable(HttpServletRequest request){
Throwable ex = null;
if (request.getAttribute("exception") != null) {
ex = (Throwable) request.getAttribute("exception");
} else if (request.getAttribute("javax.servlet.error.exception") != null) {
ex = (Throwable) request.getAttribute("javax.servlet.error.exception");
}
return ex;
}
/**
* 将ErrorStack转化为String.
*/
public static String getStackTraceAsString(Throwable e) {
if (e == null){
return "";
}
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
/**
* 判断异常是否由某些底层的异常引起.
*/
@SuppressWarnings("unchecked")
public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
Throwable cause = ex.getCause();
while (cause != null) {
for (Class<? extends Exception> causeClass : causeExceptionClasses) {
if (causeClass.isInstance(cause)) {
return true;
}
}
cause = cause.getCause();
}
return false;
}
/**
* 将CheckedException转换为UncheckedException.
*/
public static RuntimeException unchecked(Exception e) {
if (e instanceof RuntimeException) {
return (RuntimeException) e;
} else {
return new RuntimeException(e);
}
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.lang;
import java.math.BigDecimal;
import java.text.DecimalFormat;
/**
* BigDecimal工具类
* @author ThinkGem
* @version 2016年6月11日
*/
public class NumberUtils extends org.apache.commons.lang3.math.NumberUtils {
/**
* 提供精确的减法运算。
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的加法运算。
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, 10);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 格式化双精度,保留两个小数
* @return
*/
public static String formatDouble(Double b) {
BigDecimal bg = new BigDecimal(b);
return bg.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 百分比计算
* @return
*/
public static String formatScale(double one, long total) {
BigDecimal bg = new BigDecimal(one * 100 / total);
return bg.setScale(0, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 格式化数值类型
* @param data
* @param pattern
*/
public static String formatNumber(Object data, String pattern) {
DecimalFormat df = null;
if (pattern == null) {
df = new DecimalFormat();
} else {
df = new DecimalFormat(pattern);
}
return df.format(data);
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.lang;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.nustaq.serialization.FSTConfiguration;
import org.springframework.beans.BeanUtils;
import org.springframework.core.NamedThreadLocal;
/**
* 对象操作工具类, 继承org.apache.commons.lang3.ObjectUtils类
* @author ThinkGem
* @version 2018-08-11
*/
public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
/**
* 转换为Double类型
*/
public static Double toDouble(final Object val) {
if (val == null) {
return 0D;
}
try {
return NumberUtils.toDouble(StringUtils.trim(val.toString()));
} catch (Exception e) {
return 0D;
}
}
/**
* 转换为Float类型
*/
public static Float toFloat(final Object val) {
return toDouble(val).floatValue();
}
/**
* 转换为Long类型
*/
public static Long toLong(final Object val) {
return toDouble(val).longValue();
}
/**
* 转换为Integer类型
*/
public static Integer toInteger(final Object val) {
return toLong(val).intValue();
}
/**
* 转换为Boolean类型 'true', 'on', 'y', 't', 'yes' or '1' (case insensitive) will return true. Otherwise, false is returned.
*/
public static Boolean toBoolean(final Object val) {
if (val == null) {
return false;
}
return BooleanUtils.toBoolean(val.toString()) || "1".equals(val.toString());
}
/**
* 转换为字符串
* @param obj
* @return
*/
public static String toString(final Object obj) {
return toString(obj, StringUtils.EMPTY);
}
/**
* 如果对象为空,则使用defaultVal值
* @param obj
* @param defaultVal
* @return
*/
public static String toString(final Object obj, final String defaultVal) {
return obj == null ? defaultVal : obj.toString();
}
/**
* 空转空字符串("" to "" ; null to "" ; "null" to "" ; "NULL" to "" ; "Null" to "")
* @param val 需转换的值
* @return 返回转换后的值
*/
public static String toStringIgnoreNull(final Object val) {
return ObjectUtils.toStringIgnoreNull(val, StringUtils.EMPTY);
}
/**
* 空对象转空字符串 ("" to defaultVal ; null to defaultVal ; "null" to defaultVal ; "NULL" to defaultVal ; "Null" to defaultVal)
* @param val 需转换的值
* @param defaultVal 默认值
* @return 返回转换后的值
*/
public static String toStringIgnoreNull(final Object val, String defaultVal) {
String str = ObjectUtils.toString(val);
return !"".equals(str) && !"null".equals(str.trim().toLowerCase()) ? str : defaultVal;
}
/**
* 拷贝一个对象(但是子对象无法拷贝)
* @param source
* @param ignoreProperties
*/
public static Object copyBean(Object source, String... ignoreProperties){
if (source == null){
return null;
}
try {
Object target = source.getClass().newInstance();
BeanUtils.copyProperties(source, target, ignoreProperties);
return target;
} catch (InstantiationException | IllegalAccessException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* 注解到对象复制,只复制能匹配上的方法。 硕正组件用。
* @param annotation
* @param object
*/
public static void annotationToObject(Object annotation, Object object) {
if (annotation != null && object != null) {
Class<?> annotationClass = annotation.getClass();
Class<?> objectClass = object.getClass();
for (Method m : objectClass.getMethods()) {
if (StringUtils.startsWith(m.getName(), "set")) {
try {
String s = StringUtils.uncapitalize(StringUtils.substring(m.getName(), 3));
Object obj = annotationClass.getMethod(s).invoke(annotation);
if (obj != null && !"".equals(obj.toString())) {
// if (object == null){
// object = objectClass.newInstance();
// }
m.invoke(object, obj);
}
} catch (Exception e) {
// 忽略所有设置失败方法
}
}
}
}
}
/**
* 序列化对象
* @param object
* @return
*/
public static byte[] serialize(Object object) {
if (object == null){
return null;
}
long beginTime = System.currentTimeMillis();
byte[] bytes = null;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);) {
oos.writeObject(object);
bytes = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
long totalTime = System.currentTimeMillis() - beginTime;
if (totalTime > 3000){
System.out.println("Serialize time: " + TimeUtils.formatDateAgo(totalTime));
}
return bytes;
}
/**
* 反序列化对象
* @param bytes
* @return
*/
public static Object unserialize(byte[] bytes) {
if (bytes == null){
return null;
}
long beginTime = System.currentTimeMillis();
Object object = null;
if (bytes.length > 0) {
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);) {
object = ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}
long totalTime = System.currentTimeMillis() - beginTime;
if (totalTime > 3000){
System.out.println("Unserialize time: " + TimeUtils.formatDateAgo(totalTime));
}
return object;
}
// FST序列化配置对象
private static ThreadLocal<FSTConfiguration> fst = new NamedThreadLocal<FSTConfiguration>("FSTConfiguration") {
public FSTConfiguration initialValue() {
return FSTConfiguration.createDefaultConfiguration();
}
};
/**
* FST 序列化对象
* @param object
* @return
*/
public static byte[] serializeFst(Object object) {
if (object == null){
return null;
}
long beginTime = System.currentTimeMillis();
byte[] bytes = fst.get().asByteArray(object);
long totalTime = System.currentTimeMillis() - beginTime;
if (totalTime > 3000){
System.out.println("Fst serialize time: " + TimeUtils.formatDateAgo(totalTime));
}
return bytes;
}
/**
* FST 反序列化对象
* @param bytes
* @return
*/
public static Object unserializeFst(byte[] bytes) {
if (bytes == null){
return null;
}
long beginTime = System.currentTimeMillis();
Object object = fst.get().asObject(bytes);
long totalTime = System.currentTimeMillis() - beginTime;
if (totalTime > 3000){
System.out.println("Fst unserialize time: " + TimeUtils.formatDateAgo(totalTime));
}
return object;
}
/**
* 克隆一个对象(完全拷贝)
* @param source
*/
public static Object cloneBean(Object source){
if (source == null){
return null;
}
byte[] bytes = ObjectUtils.serializeFst(source);
Object target = ObjectUtils.unserializeFst(bytes);
return target;
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.lang;
import java.util.Date;
/**
* 时间计算工具类
* @author ThinkGem
* @version 2015-6-20
*/
public class TimeUtils {
/**
* 将毫秒数转换为:xx天,xx时,xx分,xx秒
*/
public static String formatDateAgo(long millisecond) {
long ms = millisecond;
int ss = 1000;
int mi = ss * 60;
int hh = mi * 60;
int dd = hh * 24;
long day = ms / dd;
long hour = (ms - day * dd) / hh;
long minute = (ms - day * dd - hour * hh) / mi;
long second = (ms - day * dd - hour * hh - minute * mi) / ss;
StringBuilder sb = new StringBuilder();
if (ms < 1000) {
sb.append(ms).append("毫秒");
} else {
if (day > 0) {
sb.append(day).append("天");
}
if (hour > 0) {
sb.append(hour).append("时");
}
if (minute > 0) {
sb.append(minute).append("分");
}
if (second > 0) {
sb.append(second).append("秒");
}
}
return sb.toString();
}
/**
* 将过去的时间转为为,刚刚,xx秒,xx分钟,xx小时前、xx天前,大于3天的显示日期
*/
public static String formatTimeAgo(String dateTime) {
return formatTimeAgo(DateUtils.parseDate(dateTime));
}
/**
* 将过去的时间转为为,刚刚,xx秒,xx分钟,xx小时前、xx天前,大于3天的显示日期
*/
public static String formatTimeAgo(Date dateTime) {
String interval = null;
// 得出的时间间隔是毫秒
long time = System.currentTimeMillis() - dateTime.getTime();
// 如果时间间隔小于10秒则显示“刚刚”time/10得出的时间间隔的单位是秒
if (time / 1000 < 10 && time / 1000 >= 0) {
interval = "刚刚";
}
// 如果时间间隔大于24小时则显示多少天前
else if (time / 3600000 < 24 * 4 && time / 3600000 >= 24) {
int d = (int) (time / (3600000 * 24));// 得出的时间间隔的单位是天
interval = d + "天前";
}
// 如果时间间隔小于24小时则显示多少小时前
else if (time / 3600000 < 24 && time / 3600000 >= 1) {
int h = (int) (time / 3600000);// 得出的时间间隔的单位是小时
interval = h + "小时前";
}
// 如果时间间隔小于60分钟则显示多少分钟前
else if (time / 60000 < 60 && time / 60000 >= 1) {
int m = (int) ((time % 3600000) / 60000);// 得出的时间间隔的单位是分钟
interval = m + "分钟前";
}
// 如果时间间隔小于60秒则显示多少秒前
else if (time / 1000 < 60 && time / 1000 >= 10) {
int se = (int) ((time % 60000) / 1000);
interval = se + "秒前";
}
// 大于3天的,则显示正常的时间,但是不显示秒
else {
interval = DateUtils.formatDate(dateTime, "yyyy-MM-dd");
}
return interval;
}
}
\ No newline at end of file
package com.jeesite.common.lang;
import java.util.Calendar;
/**
* 工作日计算工具类
* @author ThinkGem
*/
public class WorkDayUtils {
/**
* 获取日期之间的天数
* @param d1
* @param d2
* @return
*/
public int getDaysBetween(java.util.Calendar d1, java.util.Calendar d2) {
if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
java.util.Calendar swap = d1;
d1 = d2;
d2 = swap;
}
int days = d2.get(java.util.Calendar.DAY_OF_YEAR)
- d1.get(java.util.Calendar.DAY_OF_YEAR);
int y2 = d2.get(java.util.Calendar.YEAR);
if (d1.get(java.util.Calendar.YEAR) != y2) {
d1 = (java.util.Calendar) d1.clone();
do {
days += d1.getActualMaximum(java.util.Calendar.DAY_OF_YEAR);
d1.add(java.util.Calendar.YEAR, 1);
} while (d1.get(java.util.Calendar.YEAR) != y2);
}
return days;
}
/**
* 获取工作日
* @param d1
* @param d2
* @return
*/
public int getWorkingDay(java.util.Calendar d1, java.util.Calendar d2) {
int result = -1;
if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
java.util.Calendar swap = d1;
d1 = d2;
d2 = swap;
}
// int betweendays = getDaysBetween(d1, d2);
// int charge_date = 0;
int charge_start_date = 0;// 开始日期的日期偏移量
int charge_end_date = 0;// 结束日期的日期偏移量
// 日期不在同一个日期内
int stmp;
int etmp;
stmp = 7 - d1.get(Calendar.DAY_OF_WEEK);
etmp = 7 - d2.get(Calendar.DAY_OF_WEEK);
if (stmp != 0 && stmp != 6) {// 开始日期为星期六和星期日时偏移量为0
charge_start_date = stmp - 1;
}
if (etmp != 0 && etmp != 6) {// 结束日期为星期六和星期日时偏移量为0
charge_end_date = etmp - 1;
}
// }
result = (getDaysBetween(this.getNextMonday(d1), this.getNextMonday(d2)) / 7)
* 5 + charge_start_date - charge_end_date;
// System.out.println("charge_start_date>" + charge_start_date);
// System.out.println("charge_end_date>" + charge_end_date);
// System.out.println("between day is-->" + betweendays);
return result;
}
/**
* 获取中文日期
* @param date
* @return
*/
public String getChineseWeek(Calendar date) {
final String dayNames[] = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
int dayOfWeek = date.get(Calendar.DAY_OF_WEEK);
// System.out.println(dayNames[dayOfWeek - 1]);
return dayNames[dayOfWeek - 1];
}
/**
* 获得日期的下一个星期一的日期
* @param date
* @return
*/
public Calendar getNextMonday(Calendar date) {
Calendar result = null;
result = date;
do {
result = (Calendar) result.clone();
result.add(Calendar.DATE, 1);
} while (result.get(Calendar.DAY_OF_WEEK) != 2);
return result;
}
/**
* 获取休息日
* @param d1
* @param d2
* @return
*/
public int getHolidays(Calendar d1, Calendar d2) {
return this.getDaysBetween(d1, d2) - this.getWorkingDay(d1, d2);
}
// public static void main(String[] args) {
// try {
// String strDateStart = "2013-08-01";
// String strDateEnd = "2014-08-31";
//
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// Date date_start = sdf.parse(strDateStart);
// Date date_end = sdf.parse(strDateEnd);
// WorkDayUtils app = new WorkDayUtils();
// Calendar cal_start = Calendar.getInstance();
// Calendar cal_end = Calendar.getInstance();
// cal_start.setTime(date_start);
// cal_end.setTime(date_end);
// System.out.println("开始日:" + cal_start.get(Calendar.YEAR) + "-" + (cal_start.get(Calendar.MONTH) + 1)
// + "-" + cal_start.get(Calendar.DAY_OF_MONTH) + " " + app.getChineseWeek(cal_start));
// System.out.println("结束日:" + cal_end.get(Calendar.YEAR) + "-" + (cal_end.get(Calendar.MONTH) + 1)
// + "-" + cal_end.get(Calendar.DAY_OF_MONTH) + " " + app.getChineseWeek(cal_end));
// System.out.println("工作日:" + app.getWorkingDay(cal_start, cal_end));
// System.out.println("休息日:" + app.getHolidays(cal_start, cal_end));
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
}
/**
* Copyright (c) 2005-2012 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package com.jeesite.common.mapper;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.namespace.QName;
import com.jeesite.common.lang.ExceptionUtils;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.reflect.ReflectUtils;
/**
* 使用Jaxb2.0实现XML<->Java Object的Mapper.
*
* 在创建时需要设定所有需要序列化的Root对象的Class.
* 特别支持Root对象是Collection的情形.
*
* @author calvin
* @version 2013-01-15
*/
@SuppressWarnings("rawtypes")
public class JaxbMapper {
private static ConcurrentMap<Class, JAXBContext> jaxbContexts = new ConcurrentHashMap<Class, JAXBContext>();
/**
* Java Object->Xml without encoding.
*/
public static String toXml(Object root) {
Class clazz = ReflectUtils.getUserClass(root);
return toXml(root, clazz, null);
}
/**
* Java Object->Xml with encoding.
*/
public static String toXml(Object root, String encoding) {
Class clazz = ReflectUtils.getUserClass(root);
return toXml(root, clazz, encoding);
}
/**
* Java Object->Xml with encoding.
*/
public static String toXml(Object root, Class clazz, String encoding) {
try {
StringWriter writer = new StringWriter();
createMarshaller(clazz, encoding).marshal(root, writer);
return writer.toString();
} catch (JAXBException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* Java Collection->Xml without encoding, 特别支持Root Element是Collection的情形.
*/
public static String toXml(Collection<?> root, String rootName, Class clazz) {
return toXml(root, rootName, clazz, null);
}
/**
* Java Collection->Xml with encoding, 特别支持Root Element是Collection的情形.
*/
public static String toXml(Collection<?> root, String rootName, Class clazz, String encoding) {
try {
CollectionWrapper wrapper = new CollectionWrapper();
wrapper.collection = root;
JAXBElement<CollectionWrapper> wrapperElement = new JAXBElement<CollectionWrapper>(new QName(rootName),
CollectionWrapper.class, wrapper);
StringWriter writer = new StringWriter();
createMarshaller(clazz, encoding).marshal(wrapperElement, writer);
return writer.toString();
} catch (JAXBException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* Xml->Java Object.
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(String xml, Class<T> clazz) {
try {
StringReader reader = new StringReader(xml);
return (T) createUnmarshaller(clazz).unmarshal(reader);
} catch (JAXBException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* 创建Marshaller并设定encoding(可为null).
* 线程不安全,需要每次创建或pooling。
*/
public static Marshaller createMarshaller(Class clazz, String encoding) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
if (StringUtils.isNotBlank(encoding)) {
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
}
return marshaller;
} catch (JAXBException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* 创建UnMarshaller.
* 线程不安全,需要每次创建或pooling。
*/
public static Unmarshaller createUnmarshaller(Class clazz) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createUnmarshaller();
} catch (JAXBException e) {
throw ExceptionUtils.unchecked(e);
}
}
protected static JAXBContext getJaxbContext(Class clazz) {
if (clazz == null){
throw new RuntimeException("'clazz' must not be null");
}
JAXBContext jaxbContext = jaxbContexts.get(clazz);
if (jaxbContext == null) {
try {
jaxbContext = JAXBContext.newInstance(clazz, CollectionWrapper.class);
jaxbContexts.putIfAbsent(clazz, jaxbContext);
} catch (JAXBException ex) {
// throw new HttpMessageConversionException("Could not instantiate JAXBContext for class [" + clazz
// + "]: " + ex.getMessage(), ex);
throw new RuntimeException("Could not instantiate JAXBContext for class [" + clazz
+ "]: " + ex.getMessage(), ex);
}
}
return jaxbContext;
}
/**
* 封装Root Element 是 Collection的情况.
*/
public static class CollectionWrapper {
@XmlAnyElement
protected Collection<?> collection;
}
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.mapper;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import com.jeesite.common.collect.ListUtils;
import com.jeesite.common.io.PropertiesUtils;
/**
* 简单封装Jackson,实现JSON String<->Java Object的Mapper.
* 封装不同的输出风格, 使用不同的builder函数创建实例.
* @author ThinkGem
* @version 2016-3-2
*/
public class JsonMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
private static Logger logger = LoggerFactory.getLogger(JsonMapper.class);
/**
* 当前类的实例持有者(静态内部类,延迟加载,懒汉式,线程安全的单例模式)
*/
private static final class JsonMapperHolder {
private static final JsonMapper INSTANCE = new JsonMapper();
}
public JsonMapper() {
// Spring ObjectMapper 初始化配置,支持 @JsonView
new Jackson2ObjectMapperBuilder().configure(this);
// 为Null时不序列化
this.setSerializationInclusion(Include.NON_NULL);
// 允许单引号
this.configure(Feature.ALLOW_SINGLE_QUOTES, true);
// 允许不带引号的字段名称
this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 设置默认时区
this.setTimeZone(TimeZone.getTimeZone(PropertiesUtils.getInstance()
.getProperty("lang.defaultTimeZone", "GMT+08:00")));
// 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 遇到空值处理为空串
this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>(){
@Override
public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(StringUtils.EMPTY);
}
});
// // 统一默认Date类型转换格式。如果设置,Bean中的@JsonFormat将失效
// final String dataFormat = Global.getProperty("json.mapper.dataFormat");
// if (StringUtils.isNotBlank(dataFormat)){
// this.registerModule(new SimpleModule().addSerializer(Date.class, new JsonSerializer<Date>(){
// @Override
// public void serialize(Date value, JsonGenerator jgen,
// SerializerProvider provider) throws IOException, JsonProcessingException {
// if (value != null){
// jgen.writeString(DateUtils.formatDate(value, dataFormat));
// }
// }
// }));
// }
// // 进行HTML解码(先注释掉,否则会造成XSS攻击,比如菜单名称里输入<script>alert(123)</script>转josn后就会还原这个编码 ,并在浏览器中运行)。
// this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer<String>(){
// @Override
// public void serialize(String value, JsonGenerator jgen,
// SerializerProvider provider) throws IOException,
// JsonProcessingException {
// if (value != null){
// jgen.writeString(StringEscapeUtils.unescapeHtml4(value));
// }
// }
// }));
}
/**
* Object可以是POJO,也可以是Collection或数组。
* 如果对象为Null, 返回"null".
* 如果集合为空集合, 返回"[]".
*/
public String toJsonString(Object object) {
try {
return this.writeValueAsString(object);
} catch (IOException e) {
logger.warn("write to json string error:" + object, e);
return null;
}
}
/**
* 输出JSONP格式数据.
*/
public String toJsonpString(String functionName, Object object) {
return toJsonString(new JSONPObject(functionName, object));
}
/**
* 反序列化POJO或简单Collection如List<String>.
* 如果JSON字符串为Null或"null"字符串, 返回Null.
* 如果JSON字符串为"[]", 返回空集合.
* 如需反序列化复杂Collection如List<MyBean>, 请使用fromJson(String,JavaType)
* @see #fromJson(String, JavaType)
*/
public <T> T fromJsonString(String jsonString, Class<T> clazz) {
if (StringUtils.isEmpty(jsonString) || "<CLOB>".equals(jsonString)) {
return null;
}
try {
return this.readValue(jsonString, clazz);
} catch (IOException e) {
logger.warn("parse json string error:" + jsonString, e);
return null;
}
}
/**
* 反序列化复杂Collection如List<Bean>, 先使用函数createCollectionType构造类型,然后调用本函数.
* @see #createCollectionType(Class, Class...)
*/
@SuppressWarnings("unchecked")
public <T> T fromJsonString(String jsonString, JavaType javaType) {
if (StringUtils.isEmpty(jsonString) || "<CLOB>".equals(jsonString)) {
return null;
}
try {
return (T) this.readValue(jsonString, javaType);
} catch (IOException e) {
logger.warn("parse json string error:" + jsonString, e);
return null;
}
}
/**
* 构造泛型的Collection Type如:
* ArrayList<MyBean>, 则调用constructCollectionType(ArrayList.class,MyBean.class)
* HashMap<String,MyBean>, 则调用(HashMap.class,String.class, MyBean.class)
*/
public JavaType createCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
return this.getTypeFactory().constructParametricType(collectionClass, elementClasses);
}
/**
* 当JSON里只含有Bean的部分属性時,更新一个已存在Bean,只覆盖该部分的属性.
*/
@SuppressWarnings("unchecked")
public <T> T update(String jsonString, T object) {
try {
return (T) this.readerForUpdating(object).readValue(jsonString);
} catch (JsonProcessingException e) {
logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
} catch (IOException e) {
logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e);
}
return null;
}
/**
* 设定是否使用Enum的toString函数来读写Enum,
* 为False实时使用Enum的name()函数来读写Enum, 默认为False.
* 注意本函数一定要在Mapper创建后, 所有的读写动作之前调用.
*/
public JsonMapper enableEnumUseToString() {
this.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
this.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
return this;
}
/**
* 支持使用Jaxb的Annotation,使得POJO上的annotation不用与Jackson耦合。
* 默认会先查找jaxb的annotation,如果找不到再找jackson的。
*/
public JsonMapper enableJaxbAnnotation() {
JaxbAnnotationModule module = new JaxbAnnotationModule();
this.registerModule(module);
return this;
}
/**
* 取出Mapper做进一步的设置或使用其他序列化API.
*/
public ObjectMapper getMapper() {
return this;
}
/**
* 获取当前实例
*/
public static JsonMapper getInstance() {
return JsonMapperHolder.INSTANCE;
}
/**
* 对象转换为JSON字符串
*/
public static String toJson(Object object){
return JsonMapper.getInstance().toJsonString(object);
}
/**
* 对象转换为JSONP字符串
*/
public static String toJsonp(String functionName, Object object){
return JsonMapper.getInstance().toJsonpString(functionName, object);
}
/**
* JSON字符串转换为对象
*/
@SuppressWarnings("unchecked")
public static <T> T fromJson(String jsonString, Class<?> clazz){
return (T) JsonMapper.getInstance().fromJsonString(jsonString, clazz);
}
/**
* JSON字符串转换为 List<Map<String, Object>>
*/
public static List<Map<String, Object>> fromJsonForMapList(String jsonString){
List<Map<String, Object>> result = ListUtils.newArrayList();
if (StringUtils.startsWith(jsonString, "{")){
Map<String, Object> map = fromJson(jsonString, Map.class);
if (map != null){
result.add(map);
}
}else if (StringUtils.startsWith(jsonString, "[")){
List<Map<String, Object>> list = fromJson(jsonString, List.class);
if (list != null){
result = list;
}
}
return result;
}
// public static void main(String[] args) {
// List<Map<String, Object>> list = ListUtils.newArrayList();
// Map<String, Object> map = MapUtils.newHashMap();
// map.put("id", 1);
// map.put("pId", -1);
// map.put("name", "根节点");
// list.add(map);
// map = MapUtils.newHashMap();
// map.put("id", 2);
// map.put("pId", 1);
// map.put("name", "你好");
// map.put("open", true);
// list.add(map);
// String json = JsonMapper.toJson(list);
// System.out.println(json);
// List<Map<String, Object>> map2 = JsonMapper.fromJson(json, List.class);
// System.out.println(map2);
// Map<String, Object> map3 = JsonMapper.fromJson("{extendS1:{title:'站牌号',"
// + "sort:1,type:'text',maxlength:0,maxlength:30},extendS2:{title:'规模分类',"
// + "sort:2,type:'dict',dictType:'scope_category'}}", Map.class);
// System.out.println(map3);
// List<String> list2 = fromJson("[1,2]", List.class);
// System.out.println(list2);
// }
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.mapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.fasterxml.jackson.databind.JavaType;
import com.jeesite.common.io.PropertiesUtils;
/**
* XML <-> Map、Object
* @author ThinkGem
* @version 2016-9-2
*/
public class XmlMapper extends com.fasterxml.jackson.dataformat.xml.XmlMapper{
private static final long serialVersionUID = 1L;
private static Logger logger = LoggerFactory.getLogger(XmlMapper.class);
/**
* 当前类的实例持有者(静态内部类,延迟加载,懒汉式,线程安全的单例模式)
*/
private static final class XmlMapperHolder {
private static final XmlMapper INSTANCE = new XmlMapper();
}
/**
* 构造方法
*/
public XmlMapper() {
// Spring ObjectMapper 初始化配置,支持 @JsonView
new Jackson2ObjectMapperBuilder().configure(this);
// 设置默认时区
this.setTimeZone(TimeZone.getTimeZone(PropertiesUtils.getInstance()
.getProperty("lang.defaultTimeZone", "GMT+08:00")));
}
/**
* Object可以是POJO,也可以是Collection或数组。
*/
public String toXmlString(Object object) {
try {
return this.writeValueAsString(object);
} catch (IOException e) {
logger.warn("write to xml string error:" + object, e);
return null;
}
}
/**
* 反序列化POJO或简单Collection如List<String>.
* @see #fromJson(String, JavaType)
*/
public <T> T fromXmlString(String xmlString, Class<T> clazz) {
if (StringUtils.isEmpty(xmlString) || "<CLOB>".equals(xmlString)) {
return null;
}
try {
return this.readValue(xmlString, clazz);
} catch (IOException e) {
logger.warn("parse xml string error:" + xmlString, e);
return null;
}
}
/**
* 获取当前实例
*/
public static XmlMapper getInstance() {
return XmlMapperHolder.INSTANCE;
}
/**
* 对象转换为XML字符串
*/
public static String toXml(Object object){
return XmlMapper.getInstance().toXmlString(object);
}
/**
* XML字符串转换为对象
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(String jsonString, Class<?> clazz){
return (T) XmlMapper.getInstance().fromXmlString(jsonString, clazz);
}
/**
* xml转map 不带属性
* @param xmlStr
* @param needRootKey 是否需要在返回的map里加根节点键
* @throws DocumentException
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> xmlToMap(String xmlStr, boolean needRootKey) {
try {
Document doc = DocumentHelper.parseText(xmlStr);
Element root = doc.getRootElement();
Map<String, Object> map = (Map<String, Object>) xmlToMap(root);
if (root.elements().size() == 0 && root.attributes().size() == 0) {
return map;
}
if (needRootKey) {
//在返回的map里加根节点键(如果需要)
Map<String, Object> rootMap = new HashMap<String, Object>();
rootMap.put(root.getName(), map);
return rootMap;
}
return map;
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
/**
* xml转map 带属性
* @param xmlStr
* @param needRootKey 是否需要在返回的map里加根节点键
* @return
* @throws DocumentException
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> xmlToMapWithAttr(String xmlStr, boolean needRootKey) {
try {
Document doc = DocumentHelper.parseText(xmlStr);
Element root = doc.getRootElement();
Map<String, Object> map = (Map<String, Object>) xmlToMapWithAttr(root);
if (root.elements().size() == 0 && root.attributes().size() == 0) {
return map; //根节点只有一个文本内容
}
if (needRootKey) {
//在返回的map里加根节点键(如果需要)
Map<String, Object> rootMap = new HashMap<String, Object>();
rootMap.put(root.getName(), map);
return rootMap;
}
return map;
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
/**
* xml转map 不带属性
* @param element
* @return
*/
@SuppressWarnings("unchecked")
private static Object xmlToMap(Element element) {
// System.out.println(element.getName());
Map<String, Object> map = new LinkedHashMap<String, Object>();
List<Element> elements = element.elements();
if (elements.size() == 0) {
map.put(element.getName(), element.getText());
if (!element.isRootElement()) {
return element.getText();
}
} else if (elements.size() == 1) {
map.put(elements.get(0).getName(), xmlToMap(elements.get(0)));
} else if (elements.size() > 1) {
// 多个子节点的话就得考虑list的情况了,比如多个子节点有节点名称相同的
// 构造一个map用来去重
Map<String, Element> tempMap = new LinkedHashMap<String, Element>();
for (Element ele : elements) {
tempMap.put(ele.getName(), ele);
}
Set<String> keySet = tempMap.keySet();
for (String string : keySet) {
Namespace namespace = tempMap.get(string).getNamespace();
List<Element> elements2 = element.elements(new org.dom4j.QName(string, namespace));
// 如果同名的数目大于1则表示要构建list
if (elements2.size() > 1) {
List<Object> list = new ArrayList<Object>();
for (Element ele : elements2) {
list.add(xmlToMap(ele));
}
map.put(string, list);
} else {
// 同名的数量不大于1则直接递归去
map.put(string, xmlToMap(elements2.get(0)));
}
}
}
return map;
}
/**
* xml转map 带属性
* @param element
* @return
*/
@SuppressWarnings("unchecked")
private static Object xmlToMapWithAttr(Element element) {
// System.out.println(element.getName());
Map<String, Object> map = new LinkedHashMap<String, Object>();
List<Element> elements = element.elements();
List<Attribute> listAttr = element.attributes(); // 当前节点的所有属性的list
boolean hasAttributes = false;
for (Attribute attr : listAttr) {
hasAttributes = true;
map.put("@" + attr.getName(), attr.getValue());
}
if (elements.size() == 0) {
// map.put(element.getName(), element.getText());
if (hasAttributes) {
map.put("#text", element.getText());
} else {
map.put(element.getName(), element.getText());
}
if (!element.isRootElement()) {
// return element.getText();
if (!hasAttributes) {
return element.getText();
}
}
} else if (elements.size() == 1) {
map.put(elements.get(0).getName(), xmlToMapWithAttr(elements.get(0)));
} else if (elements.size() > 1) {
// 多个子节点的话就得考虑list的情况了,比如多个子节点有节点名称相同的
// 构造一个map用来去重
Map<String, Element> tempMap = new LinkedHashMap<String, Element>();
for (Element ele : elements) {
tempMap.put(ele.getName(), ele);
}
Set<String> keySet = tempMap.keySet();
for (String string : keySet) {
Namespace namespace = tempMap.get(string).getNamespace();
List<Element> elements2 = element.elements(new org.dom4j.QName(string, namespace));
// 如果同名的数目大于1则表示要构建list
if (elements2.size() > 1) {
List<Object> list = new ArrayList<Object>();
for (Element ele : elements2) {
list.add(xmlToMapWithAttr(ele));
}
map.put(string, list);
} else {
// 同名的数量不大于1则直接递归去
map.put(string, xmlToMapWithAttr(elements2.get(0)));
}
}
}
return map;
}
// public static void main(String[] args) throws Exception {
//
// File file = new File(FileUtils.getProjectPath()
// + "/../modules/core/src/main/resources/spring/spring-context-core.xml");
// String xml = FileUtils.readFileToString(file, Charset.defaultCharset());
//
// System.out.println(xmlToMap(xml, true));
// System.out.println(xmlToMapWithAttr(xml, true));
//
// XmlMapper m = XmlMapper.getInstance();
// System.out.println(m.readValue(xml, List.class));
// System.out.println(m.readValue(xml, Map.class));
//
// List<Map<String, Object>> list = ListUtils.newArrayList();
// Map<String, Object> map = MapUtils.newHashMap();
// map.put("id", 1);
// map.put("pId", -1);
// map.put("name", "根节点");
// list.add(map);
// map = MapUtils.newHashMap();
// map.put("id", 2);
// map.put("pId", 1);
// map.put("name", "你好");
// map.put("open", true);
// list.add(map);
//
// String s = XmlMapper.getInstance().writeValueAsString(list);
// System.out.println(s);
//
// list = XmlMapper.getInstance().readValue(s, List.class);
// System.out.println(list);
//
// }
}
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.common.msg;
import org.apache.commons.mail.HtmlEmail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jeesite.common.io.PropertiesUtils;
/**
* 发送电子邮件
*/
public class EmailUtils {
private final static Logger logger = LoggerFactory.getLogger(EmailUtils.class);
/**
* 发送邮件
* @param toAddress 接收地址
* @param subject 标题
* @param content 内容
* @return
*/
public static boolean send(String toAddress, String subject, String content) {
PropertiesUtils props = PropertiesUtils.getInstance();
String fromAddress = props.getProperty("msg.email.fromAddress");
String fromPassword = props.getProperty("msg.email.fromPassword");
String fromHostName = props.getProperty("msg.email.fromHostName");
String sslOnConnect = props.getProperty("msg.email.sslOnConnect", "false");
String sslSmtpPort = props.getProperty("msg.email.sslSmtpPort");
return send(fromAddress, fromPassword, fromHostName, sslOnConnect, sslSmtpPort, toAddress, subject, content);
}
/**
* 发送邮件
* @param toAddress 接收地址
* @param subject 标题
* @param content 内容
* @return
*/
public static boolean send(String fromAddress, String fromPassword, String fromHostName,
String sslOnConnect, String sslSmtpPort, String toAddress, String subject, String content) {
try {
HtmlEmail htmlEmail = new HtmlEmail();
// 发送地址
htmlEmail.setFrom(fromAddress);
// 密码校验
htmlEmail.setAuthentication(fromAddress, fromPassword);
// 发送服务器协议
htmlEmail.setHostName(fromHostName);
// SSL
if ("true".equals(sslOnConnect)) {
htmlEmail.setSSLOnConnect(true);
htmlEmail.setSslSmtpPort(sslSmtpPort);
}
// 接收地址
htmlEmail.addTo(toAddress);
// 标题
htmlEmail.setSubject(subject);
// 内容
htmlEmail.setMsg(content);
// 其他信息
htmlEmail.setCharset("utf-8");
// 发送
htmlEmail.send();
return true;
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
return false;
}
}
\ No newline at end of file
package com.jeesite.common.msg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 发送短信(请实现send方法)
*/
public class SmsUtils {
private final static Logger logger = LoggerFactory.getLogger(SmsUtils.class);
/**
* 发送短信
* @param content 短信内容
* @param mobile 接受手机号码
*/
public static String send(String content, String mobile) {
// PropertiesUtils props = PropertiesUtils.getInstance();
// String url = props.getProperty("msg.sms.url");
// String data = props.getProperty("msg.sms.data");
// String prefix = props.getProperty("msg.sms.prefix", "");
// String suffix = props.getProperty("msg.sms.suffix", "");
// Connection conn = Jsoup.connect(url);
// conn.postDataCharset("UTF-8");
// conn.method(Method.POST);
// for (String param : StringUtils.split(data, "&")){
// String[] ss = StringUtils.split(param, "=");
// if (ss.length == 1){
// conn.data(ss[0], "");
// }else if (ss.length == 2){
// conn.data(ss[0], ss[1]);
// }
// }
// // 手机号码
// conn.data("mobile", mobile);
// // 短信内容
// conn.data("content", prefix + content + suffix);
logger.warn("模拟发送短信成功!请实现 "+SmsUtils.class+" 的 send 方法。");
return "{result:0,message:\"模拟发送短信成功!\"}";
}
}
package com.jeesite.common.network;
import javax.servlet.http.HttpServletRequest;
import com.jeesite.common.codec.EncodeUtils;
import com.jeesite.common.io.PropertiesUtils;
import com.jeesite.common.lang.StringUtils;
public class IpUtils {
/**
* 获取客户端IP地址
* @param request
* @return
*/
public static String getRemoteAddr(HttpServletRequest request) {
if (request == null) {
return "unknown";
}
String ip = null;
String xffName = PropertiesUtils.getInstance()
.getProperty("shiro.remoteAddrHeaderName");
if (StringUtils.isNotBlank(xffName)){
ip = request.getHeader(xffName);
}
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (StringUtils.isNotBlank(ip)){
ip = EncodeUtils.xssFilter(ip);
ip = StringUtils.split(ip, ",")[0];
}
if (StringUtils.isBlank(ip)){
ip = "unknown";
}
return ip;
}
/**
* 是否是本地地址
* @param ip
* @return
*/
public static boolean isLocalAddr(String ip){
return StringUtils.inString(ip, "127.0.0.1", "0:0:0:0:0:0:0:1");
}
/**
* 判断IP地址为内网IP还是公网IP
*
* tcp/ip协议中,专门保留了三个IP地址区域作为私有地址,其地址范围如下:
* 10.0.0.0/8:10.0.0.0~10.255.255.255
* 172.16.0.0/12:172.16.0.0~172.31.255.255
* 192.168.0.0/16:192.168.0.0~192.168.255.255
*
* @param ip
* @return
*/
public static boolean isInternalAddr(String ip) {
if (isLocalAddr(ip)){
return true;
}
byte[] addr = textToNumericFormatV4(ip);
final byte b0 = addr[0];
final byte b1 = addr[1];
//10.x.x.x/8
final byte SECTION_1 = 0x0A;
//172.16.x.x/12
final byte SECTION_2 = (byte) 0xAC;
final byte SECTION_3 = (byte) 0x10;
final byte SECTION_4 = (byte) 0x1F;
//192.168.x.x/16
final byte SECTION_5 = (byte) 0xC0;
final byte SECTION_6 = (byte) 0xA8;
switch (b0) {
case SECTION_1:
return true;
case SECTION_2:
if (b1 >= SECTION_3 && b1 <= SECTION_4) {
return true;
}
case SECTION_5:
switch (b1) {
case SECTION_6:
return true;
}
default:
return false;
}
}
public static byte[] textToNumericFormatV4(String paramString) {
if (paramString.length() == 0) {
return null;
}
byte[] arrayOfByte = new byte[4];
String[] arrayOfString = paramString.split("\\.", -1);
try {
long l;
int i;
switch (arrayOfString.length) {
case 1:
l = Long.parseLong(arrayOfString[0]);
if ((l < 0L) || (l > 4294967295L)) {
return null;
}
arrayOfByte[0] = ((byte) (int) (l >> 24 & 0xFF));
arrayOfByte[1] = ((byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF));
arrayOfByte[2] = ((byte) (int) ((l & 0xFFFF) >> 8 & 0xFF));
arrayOfByte[3] = ((byte) (int) (l & 0xFF));
break;
case 2:
l = Integer.parseInt(arrayOfString[0]);
if ((l < 0L) || (l > 255L)) {
return null;
}
arrayOfByte[0] = ((byte) (int) (l & 0xFF));
l = Integer.parseInt(arrayOfString[1]);
if ((l < 0L) || (l > 16777215L)) {
return null;
}
arrayOfByte[1] = ((byte) (int) (l >> 16 & 0xFF));
arrayOfByte[2] = ((byte) (int) ((l & 0xFFFF) >> 8 & 0xFF));
arrayOfByte[3] = ((byte) (int) (l & 0xFF));
break;
case 3:
for (i = 0; i < 2; i++) {
l = Integer.parseInt(arrayOfString[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
arrayOfByte[i] = ((byte) (int) (l & 0xFF));
}
l = Integer.parseInt(arrayOfString[2]);
if ((l < 0L) || (l > 65535L)) {
return null;
}
arrayOfByte[2] = ((byte) (int) (l >> 8 & 0xFF));
arrayOfByte[3] = ((byte) (int) (l & 0xFF));
break;
case 4:
for (i = 0; i < 4; i++) {
l = Integer.parseInt(arrayOfString[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
arrayOfByte[i] = ((byte) (int) (l & 0xFF));
}
break;
default:
return null;
}
} catch (NumberFormatException localNumberFormatException) {
return null;
}
return arrayOfByte;
}
public static byte[] textToNumericFormatV6(String paramString) {
if (paramString.length() < 2) {
return null;
}
char[] arrayOfChar = paramString.toCharArray();
byte[] arrayOfByte1 = new byte[16];
int m = arrayOfChar.length;
int n = paramString.indexOf("%");
if (n == m - 1) {
return null;
}
if (n != -1) {
m = n;
}
int i = -1;
int i1 = 0;
int i2 = 0;
if ((arrayOfChar[i1] == ':') && (arrayOfChar[(++i1)] != ':')) {
return null;
}
int i3 = i1;
int j = 0;
int k = 0;
int i4;
while (i1 < m) {
char c = arrayOfChar[(i1++)];
i4 = Character.digit(c, 16);
if (i4 != -1) {
k <<= 4;
k |= i4;
if (k > 65535) {
return null;
}
j = 1;
} else if (c == ':') {
i3 = i1;
if (j == 0) {
if (i != -1) {
return null;
}
i = i2;
} else {
if (i1 == m) {
return null;
}
if (i2 + 2 > 16) {
return null;
}
arrayOfByte1[(i2++)] = ((byte) (k >> 8 & 0xFF));
arrayOfByte1[(i2++)] = ((byte) (k & 0xFF));
j = 0;
k = 0;
}
} else if ((c == '.') && (i2 + 4 <= 16)) {
String str = paramString.substring(i3, m);
int i5 = 0;
int i6 = 0;
while ((i6 = str.indexOf('.', i6)) != -1) {
i5++;
i6++;
}
if (i5 != 3) {
return null;
}
byte[] arrayOfByte3 = textToNumericFormatV4(str);
if (arrayOfByte3 == null) {
return null;
}
for (int i7 = 0; i7 < 4; i7++) {
arrayOfByte1[(i2++)] = arrayOfByte3[i7];
}
j = 0;
} else {
return null;
}
}
if (j != 0) {
if (i2 + 2 > 16) {
return null;
}
arrayOfByte1[(i2++)] = ((byte) (k >> 8 & 0xFF));
arrayOfByte1[(i2++)] = ((byte) (k & 0xFF));
}
if (i != -1) {
i4 = i2 - i;
if (i2 == 16) {
return null;
}
for (i1 = 1; i1 <= i4; i1++) {
arrayOfByte1[(16 - i1)] = arrayOfByte1[(i + i4 - i1)];
arrayOfByte1[(i + i4 - i1)] = 0;
}
i2 = 16;
}
if (i2 != 16) {
return null;
}
byte[] arrayOfByte2 = convertFromIPv4MappedAddress(arrayOfByte1);
if (arrayOfByte2 != null) {
return arrayOfByte2;
}
return arrayOfByte1;
}
public static boolean isIPv4LiteralAddress(String paramString) {
return textToNumericFormatV4(paramString) != null;
}
public static boolean isIPv6LiteralAddress(String paramString) {
return textToNumericFormatV6(paramString) != null;
}
public static byte[] convertFromIPv4MappedAddress(byte[] paramArrayOfByte) {
if (isIPv4MappedAddress(paramArrayOfByte)) {
byte[] arrayOfByte = new byte[4];
System.arraycopy(paramArrayOfByte, 12, arrayOfByte, 0, 4);
return arrayOfByte;
}
return null;
}
private static boolean isIPv4MappedAddress(byte[] paramArrayOfByte) {
if (paramArrayOfByte.length < 16) {
return false;
}
if ((paramArrayOfByte[0] == 0) && (paramArrayOfByte[1] == 0) && (paramArrayOfByte[2] == 0) && (paramArrayOfByte[3] == 0)
&& (paramArrayOfByte[4] == 0) && (paramArrayOfByte[5] == 0) && (paramArrayOfByte[6] == 0) && (paramArrayOfByte[7] == 0)
&& (paramArrayOfByte[8] == 0) && (paramArrayOfByte[9] == 0) && (paramArrayOfByte[10] == -1) && (paramArrayOfByte[11] == -1)) {
return true;
}
return false;
}
}
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!