xielq 5 lat temu
rodzic
commit
20fc998437
34 zmienionych plików z 3016 dodań i 0 usunięć
  1. 0 0
      README.md
  2. 119 0
      pom.xml
  3. 99 0
      src/main/java/com/uas/ps/core/encry/HmacEncoder.java
  4. 9 0
      src/main/java/com/uas/ps/core/encry/HmacMD5Encoder.java
  5. 9 0
      src/main/java/com/uas/ps/core/encry/HmacSHA1Encoder.java
  6. 9 0
      src/main/java/com/uas/ps/core/encry/HmacSHA256Encoder.java
  7. 9 0
      src/main/java/com/uas/ps/core/encry/HmacSHA384Encoder.java
  8. 9 0
      src/main/java/com/uas/ps/core/encry/HmacSHA512Encoder.java
  9. 47 0
      src/main/java/com/uas/ps/core/encry/HmacUtils.java
  10. 44 0
      src/main/java/com/uas/ps/core/encry/Md5Utils.java
  11. 43 0
      src/main/java/com/uas/ps/core/intercept/ExceptionHandlerAdvice.java
  12. 21 0
      src/main/java/com/uas/ps/core/logging/BufferedLogable.java
  13. 157 0
      src/main/java/com/uas/ps/core/logging/BufferedLogger.java
  14. 31 0
      src/main/java/com/uas/ps/core/logging/BufferedLoggerManager.java
  15. 19 0
      src/main/java/com/uas/ps/core/logging/LogService.java
  16. 488 0
      src/main/java/com/uas/ps/core/page/PageInfo.java
  17. 61 0
      src/main/java/com/uas/ps/core/page/PageParams.java
  18. 65 0
      src/main/java/com/uas/ps/core/page/criteria/CriterionExpression.java
  19. 49 0
      src/main/java/com/uas/ps/core/page/criteria/LogicalExpression.java
  20. 48 0
      src/main/java/com/uas/ps/core/page/criteria/PredicateFactory.java
  21. 231 0
      src/main/java/com/uas/ps/core/page/criteria/PredicateUtils.java
  22. 105 0
      src/main/java/com/uas/ps/core/page/criteria/SimpleExpression.java
  23. 32 0
      src/main/java/com/uas/ps/core/page/exception/IllegalOperatorException.java
  24. 60 0
      src/main/java/com/uas/ps/core/util/ArrayUtils.java
  25. 41 0
      src/main/java/com/uas/ps/core/util/Assert.java
  26. 19 0
      src/main/java/com/uas/ps/core/util/CollectionUtils.java
  27. 72 0
      src/main/java/com/uas/ps/core/util/ContextUtils.java
  28. 23 0
      src/main/java/com/uas/ps/core/util/DateFormatUtils.java
  29. 42 0
      src/main/java/com/uas/ps/core/util/ExceptionUtils.java
  30. 122 0
      src/main/java/com/uas/ps/core/util/FileBuffer.java
  31. 625 0
      src/main/java/com/uas/ps/core/util/HttpUtil.java
  32. 55 0
      src/main/java/com/uas/ps/core/util/IpHelper.java
  33. 161 0
      src/main/java/com/uas/ps/core/util/ObjectUtils.java
  34. 92 0
      src/main/java/com/uas/ps/core/util/StringUtils.java

+ 0 - 0
README.md


+ 119 - 0
pom.xml

@@ -0,0 +1,119 @@
+<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/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.uas.ps</groupId>
+        <artifactId>ps-parent</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+    <artifactId>ps-core</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-core</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-jpa</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.aspectj</groupId>
+                    <artifactId>aspectjrt</artifactId>
+                </exclusion>
+            </exclusions>
+            <optional>true</optional>
+        </dependency>
+        <!-- httpClient -->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+            <version>4.4</version>
+        </dependency>
+        <!-- security -->
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-web</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>attach-javadocs</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                        <configuration>
+                            <additionalparam>-Xdoclint:none</additionalparam>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 99 - 0
src/main/java/com/uas/ps/core/encry/HmacEncoder.java

@@ -0,0 +1,99 @@
+package com.uas.ps.core.encry;
+
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Hash-based message authentication code,利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出
+ * 
+ * @author yingp
+ *
+ */
+public class HmacEncoder {
+
+	private final String algorithm;
+
+	public HmacEncoder(String algorithm) {
+		this.algorithm = algorithm;
+	}
+
+	/**
+	 * 根据给定密钥生成算法创建密钥
+	 * 
+	 * @param algorithm
+	 *            密钥算法
+	 * @return 密钥
+	 * @throws RuntimeException
+	 *             当 {@link NoSuchAlgorithmException} 发生时
+	 */
+	public byte[] getKey() {
+		// 初始化KeyGenerator
+		KeyGenerator keyGenerator = null;
+		try {
+			keyGenerator = KeyGenerator.getInstance(algorithm);
+		} catch (NoSuchAlgorithmException e) {
+			throw new RuntimeException(e.getMessage());
+		}
+		// 产生密钥
+		SecretKey secretKey = keyGenerator.generateKey();
+		// 获得密钥
+		return secretKey.getEncoded();
+	}
+
+	/**
+	 * 转换密钥
+	 * 
+	 * @param key
+	 *            二进制密钥
+	 * @param algorithm
+	 *            密钥算法
+	 * @return 密钥
+	 */
+	private static Key toKey(byte[] key, String algorithm) {
+		// 生成密钥
+		return new SecretKeySpec(key, algorithm);
+	}
+
+	/**
+	 * 使用指定消息摘要算法计算消息摘要
+	 * 
+	 * @param data
+	 *            做消息摘要的数据
+	 * @param key
+	 *            密钥
+	 * @return 消息摘要(长度为16的字节数组)
+	 */
+	public byte[] encode(byte[] data, Key key) {
+		Mac mac = null;
+		try {
+			mac = Mac.getInstance(algorithm);
+			mac.init(key);
+		} catch (NoSuchAlgorithmException e) {
+			e.printStackTrace();
+			return new byte[0];
+		} catch (InvalidKeyException e) {
+			e.printStackTrace();
+			return new byte[0];
+		}
+		return mac.doFinal(data);
+	}
+
+	/**
+	 * 使用指定消息摘要算法计算消息摘要
+	 * 
+	 * @param data
+	 *            做消息摘要的数据
+	 * @param key
+	 *            密钥
+	 * @return 消息摘要(长度为16的字节数组)
+	 */
+	public byte[] encode(byte[] data, byte[] key) {
+		return encode(data, toKey(key, algorithm));
+	}
+
+}

+ 9 - 0
src/main/java/com/uas/ps/core/encry/HmacMD5Encoder.java

@@ -0,0 +1,9 @@
+package com.uas.ps.core.encry;
+
+public class HmacMD5Encoder extends HmacEncoder {
+
+	public HmacMD5Encoder() {
+		super("HmacMD5");
+	}
+
+}

+ 9 - 0
src/main/java/com/uas/ps/core/encry/HmacSHA1Encoder.java

@@ -0,0 +1,9 @@
+package com.uas.ps.core.encry;
+
+public class HmacSHA1Encoder extends HmacEncoder {
+
+	public HmacSHA1Encoder() {
+		super("HmacSHA1");
+	}
+
+}

+ 9 - 0
src/main/java/com/uas/ps/core/encry/HmacSHA256Encoder.java

@@ -0,0 +1,9 @@
+package com.uas.ps.core.encry;
+
+public class HmacSHA256Encoder extends HmacEncoder {
+
+	public HmacSHA256Encoder() {
+		super("HmacSHA256");
+	}
+
+}

+ 9 - 0
src/main/java/com/uas/ps/core/encry/HmacSHA384Encoder.java

@@ -0,0 +1,9 @@
+package com.uas.ps.core.encry;
+
+public class HmacSHA384Encoder extends HmacEncoder {
+
+	public HmacSHA384Encoder() {
+		super("HmacSHA384");
+	}
+
+}

+ 9 - 0
src/main/java/com/uas/ps/core/encry/HmacSHA512Encoder.java

@@ -0,0 +1,9 @@
+package com.uas.ps.core.encry;
+
+public class HmacSHA512Encoder extends HmacEncoder {
+
+	public HmacSHA512Encoder() {
+		super("HmacSHA512");
+	}
+
+}

+ 47 - 0
src/main/java/com/uas/ps/core/encry/HmacUtils.java

@@ -0,0 +1,47 @@
+package com.uas.ps.core.encry;
+
+import org.springframework.security.crypto.codec.Hex;
+
+/**
+ * Hmac加密工具
+ * 
+ * @author yingp
+ *
+ */
+public class HmacUtils {
+
+	private static HmacEncoder hmacEncoder;
+
+	// 默认约定密钥
+	private final static byte[] key = { 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 117, 98, 116, 111, 98, 46, 99, 111, 109, 47,
+			101, 114, 112, 47, 115, 97, 108, 101, 47, 111, 114, 100, 101, 114, 115, 63, 115, 111, 109, 101, 116, 104, 105, 110, 103 };
+
+	static {
+		// default algorithm: HmacSHA256
+		hmacEncoder = new HmacSHA256Encoder();
+	}
+
+	/**
+	 * 
+	 * @param message
+	 * @return 16进制密文
+	 */
+	public static String encode(Object message) {
+		byte[] encodeData = hmacEncoder.encode(String.valueOf(message).getBytes(), key);
+		return new String(Hex.encode(encodeData));
+	}
+
+	/**
+	 * 
+	 * @param message
+	 *            明文
+	 * @param key
+	 *            密钥
+	 * @return 16进制密文
+	 */
+	public static String encode(Object message, String key) {
+		byte[] encodeData = hmacEncoder.encode(String.valueOf(message).getBytes(), key.getBytes());
+		return new String(Hex.encode(encodeData));
+	}
+
+}

+ 44 - 0
src/main/java/com/uas/ps/core/encry/Md5Utils.java

@@ -0,0 +1,44 @@
+/*CopyRright (c)2014: <www.usoftchina.com>
+ */
+package com.uas.ps.core.encry;
+
+import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
+
+/**
+ * <p>
+ * 使用MD5算法.
+ * </p>
+ * 
+ * @see Md5PasswordEncoder
+ * @author yingp
+ */
+public class Md5Utils {
+
+	private static Md5PasswordEncoder md5PasswordEncoder;
+
+	static {
+		md5PasswordEncoder = new Md5PasswordEncoder();
+	}
+
+	/**
+	 * 将rawPass进行加密处理
+	 * <p>
+	 * 如果rawPass为空,将视作空字符串""
+	 * </p>
+	 * <p>
+	 * 如果salt不为空,在加密前将会与rawPass合并加密,合并方式为rawPass{salt}
+	 * </p>
+	 * 
+	 * @param rawPass
+	 *            明文
+	 * @param salt
+	 *            盐值
+	 * @return 十六进制的密文
+	 */
+	public static String encode(Object rawPass, Object salt) {
+		String pass = rawPass == null ? null : String.valueOf(rawPass);
+		salt = salt == null ? "" : salt.toString();
+		return md5PasswordEncoder.encodePassword(pass, salt);
+	}
+
+}

+ 43 - 0
src/main/java/com/uas/ps/core/intercept/ExceptionHandlerAdvice.java

@@ -0,0 +1,43 @@
+/*CopyRright (c)2014: <www.usoftchina.com>
+ */
+package com.uas.ps.core.intercept;
+
+import com.uas.ps.core.util.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * 基于Application的异常处理,以AOP的形式注册到 SpringMVC 的处理链
+ *
+ * @author sunyj
+ * @since 2017年7月11日 下午4:58:01
+ */
+@ControllerAdvice
+public class ExceptionHandlerAdvice {
+
+    private static Logger logger = LoggerFactory.getLogger(ExceptionHandlerAdvice.class);
+
+    /**
+     * 处理已捕获异常,明确传达给客户端错误码、错误信息
+     *
+     * @param e
+     * @return
+     */
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<ModelMap> handleError(Exception e) {
+        logger.error("", e);
+        ModelMap map = new ModelMap();
+        map.put("success", false);
+        map.put("message", e.getMessage());
+        map.put("detailedMessage", ExceptionUtils.getDetailedMessage(e));
+        HttpHeaders headers = new HttpHeaders();
+        headers.add("Content-Type", "application/json; charset=utf-8");
+        return new ResponseEntity<>(map, headers, HttpStatus.INTERNAL_SERVER_ERROR);
+    }
+}

+ 21 - 0
src/main/java/com/uas/ps/core/logging/BufferedLogable.java

@@ -0,0 +1,21 @@
+package com.uas.ps.core.logging;
+
+public abstract class BufferedLogable {
+
+	protected static final String separator = "#";
+
+	/**
+	 * 日志实体转化为字符串
+	 * 
+	 * @return
+	 */
+	public abstract String bufferedMessage();
+
+	/**
+	 * 字符串转化为日志实体
+	 * 
+	 * @param bufferedMessage
+	 */
+	public abstract void bufferedLog(String bufferedMessage);
+
+}

+ 157 - 0
src/main/java/com/uas/ps/core/logging/BufferedLogger.java

@@ -0,0 +1,157 @@
+package com.uas.ps.core.logging;
+
+
+import com.uas.ps.core.util.FileBuffer;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 支持异步日志记录的工具类<br>
+ * 写日志时,会尝试将日志消息快速写到本地文件,失败的情况下直接写入到持久层
+ * 
+ * @author yingp
+ *
+ */
+public abstract class BufferedLogger<T extends BufferedLogable> {
+
+	/**
+	 * 日志文件夹路径
+	 */
+	private String logPath;
+
+	/**
+	 * 日志文件名
+	 */
+	private String currentLogFile;
+
+	private Class<T> logClass;
+
+	/**
+	 * 日志文件工具
+	 */
+	private FileBuffer fileBuffer;
+
+	/**
+	 * 日志持久化service
+	 */
+	private LogService<T> logService;
+
+	public BufferedLogger() {
+	}
+
+	/**
+	 * @param basePath
+	 *            日志文件根路径
+	 * @param logClass
+	 *            日志类
+	 * @param logService
+	 *            持久化工具
+	 */
+	public BufferedLogger(String basePath, Class<T> logClass, LogService<T> logService) {
+		this.logPath = basePath + File.separator + "buff_log" + File.separator + logClass.getName();
+		this.logClass = logClass;
+		this.fileBuffer = new FileBuffer(logPath, getFileName());
+		this.logService = logService;
+		// 检查是否有遗留日志未持久化的
+		leaveOver();
+	}
+
+	/**
+	 * 写日志操作
+	 * 
+	 * @param bufferedLogable
+	 */
+	public void log(T bufferedLogable) {
+		// 先尝试写到日志文件
+		if (!fileBuffer.append(bufferedLogable.bufferedMessage()) && logService != null)
+			// 写入失败的情况下,直接持久化
+			logService.save(bufferedLogable);
+	}
+
+	/**
+	 * 读日志
+	 * 
+	 * @param buffer buffer
+	 * @return
+	 */
+	protected Set<T> read(FileBuffer buffer) {
+		Set<T> logs = new HashSet<T>();
+		String bufferedMessage = null;
+		while ((bufferedMessage = buffer.readLine()) != null) {
+			try {
+				T instance = logClass.newInstance();
+				instance.bufferedLog(bufferedMessage);
+				logs.add(instance);
+			} catch (InstantiationException e) {
+
+			} catch (IllegalAccessException e) {
+
+			}
+		}
+		return logs;
+	}
+
+	/**
+	 * 日志文件名
+	 * 
+	 * @return
+	 */
+	protected String getFileName() {
+		this.currentLogFile = String.valueOf(System.currentTimeMillis());
+		return this.currentLogFile;
+	}
+
+	/**
+	 * 切换日志文件
+	 */
+	public void switchOver() {
+		FileBuffer oldFileBuffer = this.fileBuffer;
+		if (!oldFileBuffer.isEmpty()) {
+			// 创建新的日志文件,不影响日志的写入
+			this.fileBuffer = new FileBuffer(logPath, getFileName());
+			// 旧日志文件的内容取出,并持久化
+			if (logService != null)
+				logService.save(read(oldFileBuffer));
+			// 删除旧日志文件
+			oldFileBuffer.delete();
+		}
+	}
+
+	/**
+	 * 持久化遗留日志文件
+	 */
+	protected void leaveOver() {
+		if (logService != null) {
+			File folder = new File(logPath);
+			if (folder.isDirectory()) {
+				File[] files = folder.listFiles();
+				if (files != null) {
+					String fileName = null;
+					for (File file : files) {
+						fileName = file.getName();
+						if (!fileName.equals(currentLogFile)) {
+							FileBuffer buffer = new FileBuffer(logPath, fileName);
+							try {
+								logService.save(read(buffer));
+							} catch (Exception e) {
+
+							} finally {
+								buffer.delete();
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	@Override
+	protected void finalize() throws Throwable {
+		super.finalize();
+		if (this.fileBuffer != null)
+			this.fileBuffer.close();
+	}
+
+}

+ 31 - 0
src/main/java/com/uas/ps/core/logging/BufferedLoggerManager.java

@@ -0,0 +1,31 @@
+package com.uas.ps.core.logging;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SuppressWarnings("rawtypes")
+public class BufferedLoggerManager {
+
+	private static Map<String, BufferedLogger> loggers;
+
+	static {
+		loggers = new HashMap<String, BufferedLogger>();
+	}
+
+	@SuppressWarnings("unchecked")
+	public static <T extends BufferedLogger<S>, S extends BufferedLogable> T getLogger(Class<T> cls) {
+		String clsName = cls.getName();
+		if (loggers.containsKey(clsName)) {
+			return (T) loggers.get(clsName);
+		}
+		try {
+			T instance = cls.newInstance();
+			loggers.put(clsName, instance);
+			return instance;
+		} catch (InstantiationException e) {
+		} catch (IllegalAccessException e) {
+		}
+		return null;
+	}
+
+}

+ 19 - 0
src/main/java/com/uas/ps/core/logging/LogService.java

@@ -0,0 +1,19 @@
+package com.uas.ps.core.logging;
+
+public abstract interface LogService<T extends BufferedLogable> {
+
+	/**
+	 * 日志持久化保存
+	 * 
+	 * @param logable
+	 */
+	public void save(T logable);
+
+	/**
+	 * 日志批量持久化保存
+	 * 
+	 * @param logables
+	 */
+	public void save(Iterable<T> logables);
+
+}

+ 488 - 0
src/main/java/com/uas/ps/core/page/PageInfo.java

@@ -0,0 +1,488 @@
+package com.uas.ps.core.page;
+
+import com.alibaba.fastjson.JSONObject;
+import com.uas.ps.core.page.criteria.CriterionExpression;
+import com.uas.ps.core.page.criteria.PredicateUtils;
+import com.uas.ps.core.page.exception.IllegalOperatorException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+
+/**
+ * 分页信息
+ * 
+ * @author yingp
+ * 
+ */
+public class PageInfo implements Pageable {
+
+	public PageInfo() {
+	}
+
+	/**
+	 * 分页信息
+	 * 
+	 * @param jsonPageParams
+	 */
+	public PageInfo(String jsonPageParams) {
+		PageParams params = JSONObject.parseObject(jsonPageParams,
+				PageParams.class);
+		getPageInfo(params);
+	}
+
+	public PageInfo(PageParams params) {
+		getPageInfo(params);
+	}
+
+	private void getPageInfo(PageParams params) {
+		this.pageSize = params.getCount();
+		// 不传入页面大小,默认页面大小为5
+		if (this.pageSize == 0) {
+			this.pageSize = 5;
+		}
+		// 页面大小最大不可超过1000,防止服务器崩溃
+		if (this.pageSize > 1000) {
+			throw new IllegalOperatorException("页面大小不可超过1000");
+		}
+		this.pageNumber = params.getPage();
+		// 不传入页码,默认为第一页
+		if (this.pageNumber == 0) {
+			this.pageNumber = 1;
+		}
+		this.offset = this.pageSize * (this.pageNumber - 1);
+		if (params.getFilter() != null) {
+			this.filters = JSONObject.parseObject(params.getFilter());
+		}
+		if (params.getSorting() != null) {
+			JSONObject sorting = JSONObject.parseObject(params.getSorting());
+			LinkedList<Sort.Order> orders = new LinkedList<Sort.Order>();
+			for (Object property : sorting.keySet()) {
+				orders.add(new Sort.Order(Direction.fromString(sorting.get(
+						property).toString()), property.toString()));
+			}
+			sort = new Sort(orders);
+		}
+	}
+
+	/**
+	 * 分页信息
+	 * 
+	 * @param pageNumber
+	 *            页码
+	 * @param pageSize
+	 *            单页条数
+	 */
+	public PageInfo(int pageNumber, int pageSize) {
+		this.pageNumber = pageNumber;
+		this.pageSize = pageSize;
+		this.offset = this.pageSize * (this.pageNumber - 1);
+	}
+
+	/**
+	 * 分页信息
+	 * 
+	 * @param pageNumber
+	 *            页码
+	 * @param pageSize
+	 *            单页条数
+	 */
+	public PageInfo(int pageNumber, int pageSize, int offset) {
+		this.pageNumber = pageNumber;
+		this.pageSize = pageSize;
+		this.offset = offset;
+	}
+
+	/**
+	 * 过滤器
+	 * @param key 属性
+	 * @param value 值
+	 */
+	public void filter(String key, Object value) {
+		if (filters == null) {
+			filters = new HashMap<String, Object>();
+		}
+		filters.put(key, value);
+	}
+
+	/**
+	 * 过滤器
+	 * @param key 属性
+	 * @param value 值
+	 * @param ignoreCase 是否忽略null值
+	 */
+	public void filter(String key, Object value, Boolean ignoreCase) {
+		if (filters == null) {
+			filters = new HashMap<String, Object>();
+		}
+		filters.put(key, value);
+		if (ignoreCaseMap == null) {
+			ignoreCaseMap = new HashMap<String, Boolean>();
+		}
+		if (ignoreCase) {
+			ignoreCaseMap.put(key, ignoreCase);
+		}
+	}
+
+	public void filterAll(Map<String, Object> filters) {
+		if (this.filters == null) {
+			this.filters = new HashMap<String, Object>();
+		}
+		this.filters.putAll(filters);
+	}
+
+	/**
+	 * 表达式
+	 * 
+	 * @param expression 表达式
+	 */
+	public void expression(CriterionExpression expression) {
+		if (expression != null) {
+			if (expressions == null) {
+				expressions = new HashSet<CriterionExpression>();
+			}
+			expressions.add(expression);
+		}
+	}
+
+	/**
+	 * 添加orExpression
+	 * 
+	 * @param expression 表达式
+	 */
+	public void orExpression(CriterionExpression expression) {
+		if (expression != null) {
+			if (orExpressions == null) {
+				orExpressions = new HashSet<CriterionExpression>();
+			}
+			orExpressions.add(expression);
+		}
+	}
+
+	/**
+	 * 排序
+	 * 
+	 * @param property
+	 *            需要排序的字段
+	 * @param direction
+	 *            方向
+	 */
+	public void sorting(String property, Direction direction) {
+		sort = new Sort(direction, property);
+	}
+
+	/**
+	 * 排序
+	 * 
+	 * @param direction
+	 *            方向
+	 * @param properties
+	 *            需要排序的字段
+	 */
+	public void sorting(Direction direction, String... properties) {
+		sort = new Sort(direction, properties);
+	}
+
+	private int pageNumber;
+
+	private int pageSize;
+
+	private int offset;
+
+	private Sort sort;
+
+	private Map<String, Object> filters;
+
+	private Set<CriterionExpression> expressions; // 这个里面的条件,全部都用and连接
+
+	private Set<CriterionExpression> orExpressions; // 这个里面的条件,全部都用or连接
+
+	private Map<String, Boolean> ignoreCaseMap; // 是否对这个字段 进行忽略大小写的查询
+
+	public Set<CriterionExpression> getOrExpressions() {
+		return orExpressions;
+	}
+
+	public void setOrExpressions(Set<CriterionExpression> orExpressions) {
+		this.orExpressions = orExpressions;
+	}
+
+	public int getPageNumber() {
+		return pageNumber;
+	}
+
+	public int getPageSize() {
+		return pageSize;
+	}
+
+	public int getOffset() {
+		return offset;
+	}
+
+	public Sort getSort() {
+		return sort;
+	}
+
+	public void setPageNumber(int pageNumber) {
+		this.pageNumber = pageNumber;
+	}
+
+	public void setPageSize(int pageSize) {
+		this.pageSize = pageSize;
+	}
+
+	public void setOffset(int offset) {
+		this.offset = offset;
+	}
+
+	public void setSort(Sort sort) {
+		this.sort = sort;
+	}
+
+	public Map<String, Object> getFilters() {
+		return filters;
+	}
+
+	public void setFilters(Map<String, Object> filters) {
+		this.filters = filters;
+	}
+
+	public Set<CriterionExpression> getExpressions() {
+		return expressions;
+	}
+
+	public void setExpressions(Set<CriterionExpression> expressions) {
+		this.expressions = expressions;
+	}
+
+	@SuppressWarnings("unchecked")
+	public Predicate[] getPredicates(Root<?> root, CriteriaQuery<?> query,
+			CriteriaBuilder builder) {
+		Predicate[] predicates = new Predicate[] {};
+		int i = 0;
+		if (filters != null && filters.size() > 0) {
+			Set<String> keys = filters.keySet();
+			predicates = new Predicate[keys.size()];
+			Object value = null;
+			for (String key : keys) {
+				value = filters.get(key);
+				if (value instanceof Number) {
+					Path<Number> param = PredicateUtils.getPath(root, key,
+							Number.class);
+					predicates[i++] = builder.equal(param, value);
+				} else if (value instanceof Map) {
+					predicates[i++] = getPredicate(root, query, builder, key,
+							(Map<String, Object>) value);
+				} else {
+					Path<String> param = PredicateUtils.getPath(root, key,
+							String.class);
+					if ((ignoreCaseMap == null)
+							|| (ignoreCaseMap.get(key) == null)
+							|| (!ignoreCaseMap.get(key))) {
+						predicates[i++] = builder.like(param,
+								"%" + value.toString() + "%");
+					} else { // 对数据的大小写忽略
+						predicates[i++] = builder.like(builder.upper(param),
+								"%" + value.toString().toUpperCase() + "%");
+					}
+				}
+			}
+		}
+		if (expressions != null && expressions.size() > 0) {
+			predicates = Arrays.copyOf(predicates, predicates.length
+					+ expressions.size());
+			for (CriterionExpression expression : expressions) {
+				predicates[i++] = expression.toPredicate(root, query, builder);
+			}
+		}
+
+		if (orExpressions != null && orExpressions.size() > 0) {
+			predicates = Arrays.copyOf(predicates, predicates.length + 1);
+			Predicate[] orPredicates = new Predicate[] {};
+			orPredicates = new Predicate[orExpressions.size()];
+			int j = 0;
+			for (CriterionExpression expression : orExpressions) {
+				orPredicates[j++] = expression
+						.toPredicate(root, query, builder);
+			}
+			if (orPredicates.length == 1) {
+				predicates[i++] = orPredicates[0];
+			} else {
+				predicates[i++] = builder.or(orPredicates);
+			}
+		}
+		return predicates;
+	}
+
+	/**
+	 * 传入单个字段的多个过滤条件<br>
+	 * 
+	 * @example {"filters":{"status":
+	 *          200,"date":{"gted":1441269176697,"lted":1441269176698}}}
+	 * 
+	 * @param root root
+	 * @param query query
+	 * @param builder builder
+	 * @param field
+	 *            字段名
+	 * @param valueMap
+	 *            条件map
+	 * @return
+	 */
+	private Predicate getPredicate(Root<?> root, CriteriaQuery<?> query,
+                                   CriteriaBuilder builder, String field, Map<String, Object> valueMap) {
+		Set<String> keys = valueMap.keySet();
+		Object val = null;
+		Predicate[] predicates = new Predicate[keys.size()];
+		int i = 0;
+		for (String valKey : keys) {
+			val = valueMap.get(valKey);
+			// 不等于 {"ne": "something"}
+			if (valKey.equals("ne")) {
+				Path<String> path = PredicateUtils.getPath(root, field,
+						String.class);
+				if (val != null) {
+					predicates[i++] = builder.notEqual(path,
+						String.valueOf(val));
+				} else {
+					predicates[i++] = builder.isNotNull(path);
+				}
+			// 等于 {"eq": "something"}
+			} else if (valKey.equals("eq")) {
+				Path<String> path = PredicateUtils.getPath(root, field,
+						String.class);
+				if (val != null) {
+					predicates[i++] = builder.equal(path, String.valueOf(val));
+				} else {
+					predicates[i++] = builder.isNull(path);
+				}
+			// 大于 {"gt": "something"}
+			} else if (valKey.equals("gt")) {
+				Path<String> path = PredicateUtils.getPath(root, field,
+						String.class);
+				predicates[i++] = builder
+						.greaterThan(path, String.valueOf(val));
+			// 小于 {"lt": "something"}
+			} else if (valKey.equals("lt")) {
+				Path<String> path = PredicateUtils.getPath(root, field,
+						String.class);
+				predicates[i++] = builder.lessThan(path, String.valueOf(val));
+			// 大于等于 {"gte": "something"}
+			} else if (valKey.equals("gte")) {
+				Path<String> path = PredicateUtils.getPath(root, field,
+						String.class);
+				predicates[i++] = builder.greaterThanOrEqualTo(path,
+						String.valueOf(val));
+			// 小于等于 {"lte": "something"}
+			} else if (valKey.equals("lte")) {
+				Path<String> path = PredicateUtils.getPath(root, field,
+						String.class);
+				predicates[i++] = builder.lessThanOrEqualTo(path,
+						String.valueOf(val));
+			// 日期大于 {"gtd": 1441269176697}
+			} else if (valKey.equals("gtd")) {
+				Path<Date> path = PredicateUtils.getPath(root, field,
+						Date.class);
+				predicates[i++] = builder.greaterThan(path,
+						new Date(Long.parseLong(String.valueOf(val))));
+			// 日期小于 {"ltd": 1441269176697}
+			} else if (valKey.equals("ltd")) {
+				Path<Date> path = PredicateUtils.getPath(root, field,
+						Date.class);
+				predicates[i++] = builder.lessThan(path,
+						new Date(Long.parseLong(String.valueOf(val))));
+			// 日期大于等于 {"gted": 1441269176697}
+			} else if (valKey.equals("gted")) {
+				Path<Date> path = PredicateUtils.getPath(root, field,
+						Date.class);
+				predicates[i++] = builder.greaterThanOrEqualTo(path, new Date(
+						Long.parseLong(String.valueOf(val))));
+			// 日期小于等于 {"lted": 1441269176697}
+			} else if (valKey.equals("lted")) {
+				Path<Date> path = PredicateUtils.getPath(root, field,
+						Date.class);
+				predicates[i++] = builder.lessThanOrEqualTo(path,
+						new Date(Long.parseLong(String.valueOf(val))));
+			} else {
+				Path<String> path = PredicateUtils.getPath(root, field,
+						String.class);
+				predicates[i++] = builder.equal(path, String.valueOf(val));
+			}
+		}
+		return builder.and(predicates);
+	}
+
+	public Pageable next() {
+		return null;
+	}
+
+	public Pageable previousOrFirst() {
+		return null;
+	}
+
+	public Pageable first() {
+		return null;
+	}
+
+	public boolean hasPrevious() {
+		return false;
+	}
+
+	public Pageable getPageable() {
+		final Pageable scope = this;
+		return new Pageable() {
+
+			@Override
+			public Pageable previousOrFirst() {
+				return scope.previousOrFirst();
+			}
+
+			@Override
+			public Pageable next() {
+				return scope.next();
+			}
+
+			@Override
+			public boolean hasPrevious() {
+				return scope.hasPrevious();
+			}
+
+			@Override
+			public Sort getSort() {
+				return scope.getSort();
+			}
+
+			@Override
+			public int getPageSize() {
+				return scope.getPageSize();
+			}
+
+			@Override
+			public int getPageNumber() {
+				return scope.getPageNumber();
+			}
+
+			@Override
+			public int getOffset() {
+				return scope.getOffset();
+			}
+
+			@Override
+			public Pageable first() {
+				return scope.first();
+			}
+		};
+	}
+
+}

+ 61 - 0
src/main/java/com/uas/ps/core/page/PageParams.java

@@ -0,0 +1,61 @@
+package com.uas.ps.core.page;
+
+import java.io.Serializable;
+
+public class PageParams implements Serializable {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	private int count;
+	private int page;
+	private String filter;
+	private String sorting;
+
+	public int getCount() {
+		return count;
+	}
+
+	public void setCount(int count) {
+		this.count = count;
+	}
+
+	public int getPage() {
+		return page;
+	}
+
+	public void setPage(int page) {
+		this.page = page;
+	}
+
+	public String getFilter() {
+		return filter;
+	}
+
+	public void setFilter(String filter) {
+		this.filter = filter;
+	}
+
+	public String getSorting() {
+		return sorting;
+	}
+
+	public void setSorting(String sorting) {
+		this.sorting = sorting;
+	}
+
+	public PageParams(int count, int page, String filter, String sorting) {
+		super();
+		this.count = count;
+		this.page = page;
+		this.filter = filter;
+		this.sorting = sorting;
+	}
+
+	public PageParams() {
+		super();
+	}
+
+
+}

+ 65 - 0
src/main/java/com/uas/ps/core/page/criteria/CriterionExpression.java

@@ -0,0 +1,65 @@
+package com.uas.ps.core.page.criteria;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+/**
+ * 条件表达式接口
+ * 
+ * @author yingp
+ * 
+ */
+public interface CriterionExpression {
+
+	public enum Operator {
+		/**
+		 * 等于
+		 */
+		EQ,
+		/**
+		 * 不等于
+		 */
+		NE,
+		/**
+		 * like
+		 */
+		LIKE,
+		/**
+		 * 大于
+		 */
+		GT,
+		/**
+		 * 小于
+		 */
+		LT,
+		/**
+		 * 大于等于
+		 */
+		GTE,
+		/**
+		 * 小于等于
+		 */
+		LTE,
+		/**
+		 * and
+		 */
+		AND,
+		/**
+		 * or
+		 */
+		OR,
+		/**
+		 * is null
+		 */
+		IS_NULL,
+		/**
+		 * is not null
+		 */
+		IS_NOT_NULL
+	}
+
+	public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder);
+
+}

+ 49 - 0
src/main/java/com/uas/ps/core/page/criteria/LogicalExpression.java

@@ -0,0 +1,49 @@
+package com.uas.ps.core.page.criteria;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+/**
+ * 逻辑条件表达式 用于复杂条件时使用
+ * 
+ * @author yingp
+ * 
+ */
+public class LogicalExpression implements CriterionExpression {
+
+	/**
+	 * 逻辑表达式中包含的表达式
+	 */
+	private CriterionExpression[] expressions;
+
+	/**
+	 * 运算符
+	 */
+	private Operator operator;
+
+	public LogicalExpression(CriterionExpression[] expressions, Operator operator) {
+		this.expressions = expressions;
+		this.operator = operator;
+	}
+
+	public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
+		List<Predicate> predicates = new ArrayList<Predicate>();
+		for (int i = 0, len = this.expressions.length; i < len; i++) {
+			predicates.add(this.expressions[i].toPredicate(root, query, builder));
+		}
+		switch (operator) {
+		case OR:
+			return builder.or(predicates.toArray(new Predicate[predicates.size()]));
+		case AND:
+			return builder.and(predicates.toArray(new Predicate[predicates.size()]));
+		default:
+			return null;
+		}
+
+	}
+
+}

+ 48 - 0
src/main/java/com/uas/ps/core/page/criteria/PredicateFactory.java

@@ -0,0 +1,48 @@
+package com.uas.ps.core.page.criteria;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import org.springframework.data.jpa.domain.Specification;
+
+/**
+ * 特殊查询条件的容器
+ * 
+ * @author yingp
+ * 
+ * @param <T>
+ */
+public class PredicateFactory<T> implements Specification<T> {
+
+	private List<CriterionExpression> expressions = new ArrayList<CriterionExpression>();
+
+	public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
+			CriteriaBuilder builder) {
+		if (!expressions.isEmpty()) {
+			List<Predicate> predicates = new ArrayList<Predicate>();
+			for (CriterionExpression c : expressions) {
+				predicates.add(c.toPredicate(root, query, builder));
+			}
+			// 将所有条件用 and 联合起来
+			if (predicates.size() > 0) {
+				return builder.and(predicates.toArray(new Predicate[predicates.size()]));
+			}
+		}
+		return builder.conjunction();
+	}
+
+	/**
+	 * 增加简单条件表达式
+	 * 
+	 */
+	public PredicateFactory<T> add(CriterionExpression expression) {
+		if (expression != null) {
+			expressions.add(expression);
+		}
+		return this;
+	}
+
+}

+ 231 - 0
src/main/java/com/uas/ps/core/page/criteria/PredicateUtils.java

@@ -0,0 +1,231 @@
+package com.uas.ps.core.page.criteria;
+
+import java.util.Collection;
+import javax.persistence.criteria.Path;
+import org.hibernate.criterion.MatchMode;
+import org.springframework.util.StringUtils;
+
+/**
+ * 条件构造器 用于创建条件表达式
+ * 
+ */
+public class PredicateUtils {
+
+	/**
+	 *
+	 * 等于
+	 *
+	 * @param param
+	 * @param value 注意和modul对应字段的数据类型对应
+	 * @param ignoreNull 是否忽略字段值为null
+	 * @return
+	 */
+	public static SimpleExpression eq(String param, Object value, boolean ignoreNull) {
+		if (StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.EQ);
+	}
+
+	/**
+	 * 不等于
+	 * 
+	 * @param param
+	 * @param value 注意和modul对应字段的数据类型对应
+	 * @param ignoreNull
+	 * @return
+	 */
+	public static SimpleExpression ne(String param, Object value, boolean ignoreNull) {
+		if (ignoreNull && StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.NE);
+	}
+
+	/**
+	 * 模糊匹配
+	 * 
+	 * @param param
+	 * @param value
+	 * @param ignoreNull
+	 * @return
+	 */
+	public static SimpleExpression like(String param, String value, boolean ignoreNull) {
+		if (ignoreNull && StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.LIKE);
+	}
+	
+	/**
+	 * 模糊匹配
+	 * 
+	 * @param param
+	 * @param value
+	 * @param ignoreNull
+	 * @return
+	 */
+	public static SimpleExpression like(String param, String value, boolean ignoreNull, boolean ignoreCase) {
+		if (ignoreNull && StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.LIKE, ignoreCase);
+	}
+
+	/**
+	 * 
+	 * @param param
+	 * @param value 注意和modul对应字段的数据类型对应
+	 * @param matchMode
+	 * @param ignoreNull
+	 * @return
+	 */
+	public static SimpleExpression like(String param, String value, MatchMode matchMode, boolean ignoreNull) {
+		if (ignoreNull && StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.LIKE);
+	}
+
+	/**
+	 * 大于
+	 * 
+	 * @param param
+	 * @param value 注意和modul对应字段的数据类型对应
+	 * @param ignoreNull
+	 * @return
+	 */
+	public static SimpleExpression gt(String param, Object value, boolean ignoreNull) {
+		if (ignoreNull && StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.GT);
+	}
+
+	/**
+	 * 小于
+	 * 
+	 * @param param
+	 * @param value 注意和modul对应字段的数据类型对应
+	 * @param ignoreNull
+	 * @return
+	 */
+	public static SimpleExpression lt(String param, Object value, boolean ignoreNull) {
+		if (ignoreNull && StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.LT);
+	}
+
+	/**
+	 * 大于等于
+	 * 
+	 * @param param
+	 * @param value 注意和modul对应字段的数据类型对应
+	 * @param ignoreNull
+	 * @return
+	 */
+	public static SimpleExpression gte(String param, Object value, boolean ignoreNull) {
+		if (ignoreNull && StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.GTE);
+	}
+
+	/**
+	 * 小于等于
+	 * 
+	 * @param param
+	 * @param value 注意和modul对应字段的数据类型对应
+	 * @param ignoreNull
+	 * @return
+	 */
+	public static SimpleExpression lte(String param, Object value, boolean ignoreNull) {
+		if (ignoreNull && StringUtils.isEmpty(value))
+			return null;
+		return new SimpleExpression(param, value, CriterionExpression.Operator.LTE);
+	}
+
+	/**
+	 * 为空
+	 * 
+	 * @param param
+	 * @return
+	 */
+	public static SimpleExpression isNull(String param) {
+		return new SimpleExpression(param, CriterionExpression.Operator.IS_NULL);
+	}
+
+	/**
+	 * 不为空
+	 * 
+	 * @param param
+	 * @return
+	 */
+	public static SimpleExpression isNotNull(String param) {
+		return new SimpleExpression(param, CriterionExpression.Operator.IS_NOT_NULL);
+	}
+
+	/**
+	 * 并且
+	 * 
+	 * @param expressions
+	 * @return
+	 */
+	public static LogicalExpression and(CriterionExpression... expressions) {
+		return new LogicalExpression(expressions, CriterionExpression.Operator.AND);
+	}
+
+	/**
+	 * 或者
+	 * 
+	 * @param expressions
+	 * @return
+	 */
+	public static LogicalExpression or(CriterionExpression... expressions) {
+		return new LogicalExpression(expressions, CriterionExpression.Operator.OR);
+	}
+
+	/**
+	 * 包含于
+	 * 
+	 * @param param
+	 * @param value
+	 * @return
+	 */
+	@SuppressWarnings("rawtypes")
+	public static LogicalExpression in(String param, Collection value, boolean ignoreNull) {
+		if (ignoreNull && (value == null || value.isEmpty())) {
+			return null;
+		}
+		SimpleExpression[] ses = new SimpleExpression[value.size()];
+		int i = 0;
+		for (Object obj : value) {
+			ses[i] = new SimpleExpression(param, obj, CriterionExpression.Operator.EQ);
+			i++;
+		}
+		return new LogicalExpression(ses, CriterionExpression.Operator.OR);
+	}
+
+	/**
+	 * 包含于
+	 * 
+	 * @param param
+	 * @param values
+	 * @return
+	 */
+	public static LogicalExpression in(String param, Object[] values, boolean ignoreNull) {
+		if (ignoreNull && (values == null || values.length == 0)) {
+			return null;
+		}
+		SimpleExpression[] ses = new SimpleExpression[values.length];
+		int i = 0;
+		for (Object obj : values) {
+			ses[i] = new SimpleExpression(param, obj, CriterionExpression.Operator.EQ);
+			i++;
+		}
+		return new LogicalExpression(ses, CriterionExpression.Operator.OR);
+	}
+
+	@SuppressWarnings("unchecked")
+	public static <T, R> Path<R> getPath(Path<T> root, String path, Class<R> resultType) {
+		String[] pathElements = path.split("\\.");
+		Path<?> retVal = root;
+		for (String pathEl : pathElements) {
+			retVal = (Path<R>) retVal.get(pathEl);
+		}
+		return (Path<R>) retVal;
+	}
+}

+ 105 - 0
src/main/java/com/uas/ps/core/page/criteria/SimpleExpression.java

@@ -0,0 +1,105 @@
+package com.uas.ps.core.page.criteria;
+
+import javax.persistence.criteria.*;
+import org.springframework.util.StringUtils;
+
+/**
+ * 条件表达式
+ * 
+ * @author yingp
+ * 
+ */
+public class SimpleExpression implements CriterionExpression {
+
+	/**
+	 * 属性
+	 */
+	private String param;
+	/**
+	 * 值
+	 */
+	private Object value;
+	
+	/*
+	 * 是否忽略大小写
+	 */
+	private boolean ignoreCase;
+	/**
+	 * 运算符
+	 */
+	private Operator operator;
+	
+	public SimpleExpression(String param, Object value, Operator operator) {
+		this.param = param;
+		this.value = value;
+		this.operator = operator;
+		this.ignoreCase = false;
+	}
+
+	public SimpleExpression(String param, Object value, Operator operator, boolean ignoreCase) {
+		this.param = param;
+		this.value = value;
+		this.operator = operator;
+		this.ignoreCase = ignoreCase;
+	}
+
+	protected SimpleExpression(String param, Operator operator) {
+		this.param = param;
+		this.operator = operator;
+	}
+
+	public String getParam() {
+		return param;
+	}
+
+	public Object getValue() {
+		return value;
+	}
+
+	public Operator getOperator() {
+		return operator;
+	}
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
+		Path expression = null;
+		if (param.contains(".")) {
+			String[] names = StringUtils.split(param, ".");
+			expression = root.get(names[0]);
+			for (int i = 1; i < names.length; i++) {
+				expression = expression.get(names[i]);
+			}
+		} else {
+			expression = root.get(param);
+		}
+
+		switch (operator) {
+		case EQ:
+			return builder.equal(expression, value);
+		case NE:
+			return builder.notEqual(expression, value);
+		case LIKE:
+				if (ignoreCase) {
+					return builder.like(builder.upper((Expression<String>) expression), "%" + value.toString().toUpperCase() + "%");
+				} else {
+					return builder.like((Expression<String>) expression, "%" + value + "%");
+				}
+			
+		case LT:
+			return builder.lessThan(expression, (Comparable) value);
+		case GT:
+			return builder.greaterThan(expression, (Comparable) value);
+		case LTE:
+			return builder.lessThanOrEqualTo(expression, (Comparable) value);
+		case GTE:
+			return builder.greaterThanOrEqualTo(expression, (Comparable) value);
+		case IS_NULL:
+			return builder.isNull(expression);
+		case IS_NOT_NULL:
+			return builder.isNotNull(expression);
+		default:
+			return null;
+		}
+	}
+
+}

+ 32 - 0
src/main/java/com/uas/ps/core/page/exception/IllegalOperatorException.java

@@ -0,0 +1,32 @@
+package com.uas.ps.core.page.exception;
+
+/**
+ * 非法操作
+ * 
+ * @author yingp
+ * 
+ */
+public class IllegalOperatorException extends RuntimeException {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 3958657497510022539L;
+
+	public IllegalOperatorException() {
+		super("非法操作");
+	}
+
+	public IllegalOperatorException(String paramString) {
+		super(paramString);
+	}
+
+	public IllegalOperatorException(String paramString, Throwable paramThrowable) {
+		super(paramString, paramThrowable);
+	}
+
+	public IllegalOperatorException(Throwable paramThrowable) {
+		super(paramThrowable);
+	}
+
+}

+ 60 - 0
src/main/java/com/uas/ps/core/util/ArrayUtils.java

@@ -0,0 +1,60 @@
+package com.uas.ps.core.util;
+
+import java.util.Arrays;
+
+/**
+ * @author sunyj
+ * @since 2017年4月21日 下午9:01:53
+ */
+public class ArrayUtils {
+
+    public static boolean isEmpty(Object[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static boolean isEmpty(long[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static boolean isEmpty(int[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static boolean isEmpty(short[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static boolean isEmpty(char[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static boolean isEmpty(byte[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static boolean isEmpty(double[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static boolean isEmpty(float[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static boolean isEmpty(boolean[] array) {
+        return array == null || array.length == 0;
+    }
+
+    public static <T> T[] concat(T[] first, T[]... rest) {
+        int totalLength = first.length;
+        for (T[] array : rest) {
+            totalLength += array.length;
+        }
+        T[] result = Arrays.copyOf(first, totalLength);
+        int offset = first.length;
+        for (T[] array : rest) {
+            System.arraycopy(array, 0, result, offset, array.length);
+            offset += array.length;
+        }
+        return result;
+    }
+}

+ 41 - 0
src/main/java/com/uas/ps/core/util/Assert.java

@@ -0,0 +1,41 @@
+package com.uas.ps.core.util;
+
+/**
+ * 断言
+ *
+ * @author sunyj
+ * @since 2018/1/17 10:23
+ */
+public class Assert {
+
+    public static void hasText(String text, String message) {
+        if (!StringUtils.hasText(text)) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    public static void notNull(Object object, String message) {
+        if (object == null) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    public static void notEmpty(Object object, String message) {
+        if (ObjectUtils.isEmpty(object)) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    public static void greaterThanZero(Number number, String message) {
+        notNull(number, message);
+        if (!(number.doubleValue() > 0)) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    public static void isTrue(boolean expression, String message) {
+        if (!expression) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+}

+ 19 - 0
src/main/java/com/uas/ps/core/util/CollectionUtils.java

@@ -0,0 +1,19 @@
+package com.uas.ps.core.util;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author sunyj
+ * @since 2017年4月21日 下午9:43:31
+ */
+public class CollectionUtils {
+
+    public static boolean isEmpty(Collection<?> coll) {
+        return (coll == null || coll.isEmpty());
+    }
+
+    public static boolean isEmpty(Map<?, ?> map) {
+        return (map == null || map.isEmpty());
+    }
+}

+ 72 - 0
src/main/java/com/uas/ps/core/util/ContextUtils.java

@@ -0,0 +1,72 @@
+package com.uas.ps.core.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * spring容器上下文对象
+ *
+ * @author yingp
+ */
+public class ContextUtils {
+    private static ApplicationContext applicationContext;
+
+    private static Logger logger = LoggerFactory.getLogger(ContextUtils.class);
+
+    public static ApplicationContext getApplicationContext() {
+        synchronized (ContextUtils.class) {
+            while (applicationContext == null) {
+                try {
+                    logger.debug("getApplicationContext, wait...");
+                    ContextUtils.class.wait(60000);
+                    if (applicationContext == null) {
+                        logger.warn("Have been waiting for ApplicationContext to be set for 1 minute", new Exception());
+                    }
+                } catch (InterruptedException ex) {
+                    logger.debug("getApplicationContext, wait interrupted");
+                }
+            }
+            return applicationContext;
+        }
+    }
+
+    public static void setApplicationContext(ApplicationContext applicationContext) {
+        synchronized (ContextUtils.class) {
+            logger.debug("setApplicationContext, notifyAll");
+            ContextUtils.applicationContext = applicationContext;
+            ContextUtils.class.notifyAll();
+        }
+    }
+
+    /**
+     * 获取bean
+     *
+     * @param name
+     * @return
+     */
+    public static Object getBean(String name) {
+        return getApplicationContext().getBean(name);
+    }
+
+    /**
+     * 获取bean
+     *
+     * @param cls
+     * @return
+     */
+    public static <T> T getBean(Class<T> cls) {
+        return getApplicationContext().getBean(cls);
+    }
+
+    /**
+     * 触发事件
+     *
+     * @param event
+     */
+    public static void publishEvent(ApplicationEvent event) {
+        getApplicationContext().publishEvent(event);
+    }
+
+}

+ 23 - 0
src/main/java/com/uas/ps/core/util/DateFormatUtils.java

@@ -0,0 +1,23 @@
+package com.uas.ps.core.util;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+/**
+ * @author sunyj
+ * @since 2018/1/6 17:34
+ */
+public class DateFormatUtils {
+
+    public static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
+
+    public static boolean isDateTime(String input) {
+        return input != null && input.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}");
+    }
+
+    public static boolean isDate(String input) {
+        return input != null && input.matches("\\d{4}-\\d{2}-\\d{2}");
+    }
+}

+ 42 - 0
src/main/java/com/uas/ps/core/util/ExceptionUtils.java

@@ -0,0 +1,42 @@
+package com.uas.ps.core.util;
+
+/**
+ * 处理异常的工具类
+ *
+ * @author sunyj
+ * @since 2017年8月10日 下午3:26:55
+ */
+public class ExceptionUtils {
+
+    /**
+     * 获取异常及其Cause拼接成的字符串
+     *
+     * @param e 异常
+     * @return 拼接后的结果
+     */
+    public static String getMessage(Throwable e) {
+        StringBuilder sb = new StringBuilder(e.toString());
+        if (e.getCause() != null) {
+            sb.append("\nCaused by: ").append(getMessage(e.getCause()));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 获取异常及其Cause的StackTrace拼接成的字符串
+     *
+     * @param e 异常
+     * @return 拼接后的结果
+     */
+    public static String getDetailedMessage(Throwable e) {
+        StringBuilder sb = new StringBuilder(e.toString());
+        StackTraceElement[] stackTraceElements = e.getStackTrace();
+        for (StackTraceElement stackTraceElement : stackTraceElements) {
+            sb.append("\n\t").append(stackTraceElement.toString());
+        }
+        if (e.getCause() != null) {
+            sb.append("\nCaused by: ").append(getDetailedMessage(e.getCause()));
+        }
+        return sb.toString();
+    }
+}

+ 122 - 0
src/main/java/com/uas/ps/core/util/FileBuffer.java

@@ -0,0 +1,122 @@
+package com.uas.ps.core.util;
+
+import java.io.*;
+
+public class FileBuffer {
+
+	private String filePath;
+	private BufferedWriter writer;
+	private BufferedReader reader;
+
+	/**
+	 * @param folderPath
+	 *            文件夹目录
+	 * @param fileName
+	 *            文件名
+	 */
+	public FileBuffer(String folderPath, String fileName) {
+		File file = new File(folderPath);
+		if (!file.isDirectory())
+			file.mkdirs();
+		this.filePath = folderPath + File.separator + fileName;
+	}
+
+	/**
+	 * 文件里面追加一行内容
+	 * 
+	 * @param content
+	 * @return
+	 */
+	public synchronized boolean append(String content) {
+		if (writer == null)
+			try {
+				File file = new File(filePath);
+				if (!file.exists())
+					file.createNewFile();
+				writer = new BufferedWriter(new FileWriter(file, true));
+			} catch (IOException e) {
+				return false;
+			}
+		else
+			try {
+				writer.write("\r\n");
+			} catch (IOException e1) {
+				return false;
+			}
+		try {
+			writer.write(content);
+			writer.flush();
+		} catch (IOException e) {
+			return false;
+		}
+		return true;
+	}
+
+	public synchronized String readLine() {
+		if (writer != null)
+			close();
+		if (reader == null) {
+			File file = new File(filePath);
+			if (file.exists()) {
+				try {
+					InputStreamReader streamReader = new InputStreamReader(new FileInputStream(file));
+					reader = new BufferedReader(streamReader);
+				} catch (FileNotFoundException e) {
+					return null;
+				}
+			}
+		}
+		if (reader != null)
+			try {
+				return reader.readLine();
+			} catch (IOException e) {
+			}
+		return null;
+	}
+
+	/**
+	 * 关闭文件写入流
+	 */
+	public synchronized void close() {
+		if (writer != null)
+			try {
+				writer.close();
+			} catch (IOException e) {
+
+			} finally {
+				writer = null;
+			}
+	}
+
+	public synchronized void delete() {
+		if (writer != null)
+			try {
+				writer.close();
+			} catch (IOException e1) {
+			} finally {
+				writer = null;
+			}
+		if (reader != null)
+			try {
+				reader.close();
+			} catch (IOException e) {
+			} finally {
+				reader = null;
+			}
+		File file = new File(filePath);
+		if (file.exists())
+			file.delete();
+	}
+
+	public synchronized boolean isEmpty() {
+		boolean empty = this.writer == null;
+		if (!empty) {
+			File file = new File(filePath);
+			empty = !file.exists();
+			if (!empty)
+				empty = file.length() == 0;
+		}
+		return empty;
+	}
+
+}

+ 625 - 0
src/main/java/com/uas/ps/core/util/HttpUtil.java

@@ -0,0 +1,625 @@
+package com.uas.ps.core.util;
+
+import com.alibaba.fastjson.JSON;
+import com.uas.ps.core.encry.HmacUtils;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.http.Consts;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.entity.mime.content.FileBody;
+import org.apache.http.entity.mime.content.StringBody;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.protocol.HTTP;
+import org.apache.http.util.EntityUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.util.StreamUtils;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * HTTP工具类,封装http请求
+ * 
+ * @author suntg
+ */
+public class HttpUtil {
+
+	/**
+	 * 发送GET请求
+	 * 
+	 * @param url url
+	 * @param params params
+	 * @return Response
+	 * @throws Exception Exception
+	 */
+	public static Response sendGetRequest(String url, Map<String, ?> params) throws Exception {
+		return sendGetRequest(url, params, false);
+	}
+
+	/**
+	 * 发送GET请求
+	 * 
+	 * @param url url
+	 * @param params params
+	 * @param sign
+	 *            是否发送签名
+	 * @return Response
+	 * @throws Exception Exception
+	 */
+	@SuppressWarnings("unchecked")
+	public static Response sendGetRequest(String url, Map<String, ?> params, boolean sign) throws Exception {
+		return sendRequest(RequestMethod.GET, url, (Map<String, Object>) params, sign, false);
+	}
+
+	/**
+	 * 暂时先使用这种方法(短信接口调用)
+	 * @param url  url
+	 * @param param  param
+	 * @return String
+	 */
+	public static String sendPost(String url, String param) {
+		PrintWriter out = null;
+		BufferedReader in = null;
+		String result = "";
+		try {
+			URL realUrl = new URL(url);
+			// 打开和URL之间的连接
+			URLConnection conn = realUrl.openConnection();
+			// 设置通用的请求属性
+			conn.setRequestProperty("content-type", "application/json");
+			conn.setRequestProperty("accept", "*/*");
+			conn.setRequestProperty("connection", "Keep-Alive");
+			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+			// 发送POST请求必须设置如下两行
+			conn.setDoOutput(true);
+			conn.setDoInput(true);
+			// 获取URLConnection对象对应的输出流
+			out = new PrintWriter(conn.getOutputStream());
+			// 发送请求参数
+			out.print(param);
+			// flush输出流的缓冲
+			out.flush();
+			// 定义BufferedReader输入流来读取URL的响应
+			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+			String line;
+			while ((line = in.readLine()) != null) {
+				result += line;
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		// 使用finally块来关闭输出流、输入流
+		finally {
+			try {
+				if (out != null) {
+					out.close();
+				}
+				if (in != null) {
+					in.close();
+				}
+			} catch (IOException ex) {
+				ex.printStackTrace();
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 发送POST请求
+	 * 
+	 * @param url url
+	 * @param  params params
+	 * @return Response
+	 * @throws Exception Exception
+	 */
+	public static Response sendPostRequest(String url, Map<String, ?> params) throws Exception {
+		return sendPostRequest(url, params, false);
+	}
+
+	/**
+	 * 发送POST请求
+	 * 
+	 * @param url url
+	 * @param params params
+	 * @param sign
+	 *            是否发送签名
+	 * @return Response
+	 * @throws Exception Exception
+	 */
+	@SuppressWarnings("unchecked")
+	public static Response sendPostRequest(String url, Map<String, ?> params, boolean sign) throws Exception {
+		return sendRequest(RequestMethod.POST, url, (Map<String, Object>) params, sign, true);
+	}
+
+	/**
+	 * 发送POST请求
+	 * 
+	 * @param url url
+	 * @param params params
+	 * @param sign
+	 *            是否发送签名
+	 * @param encode
+	 *            是否使用URLEncode
+	 * @return Response
+	 * @throws Exception Exception
+	 */
+	@SuppressWarnings("unchecked")
+	public static Response sendPostRequest(String url, Map<String, ?> params, boolean sign, boolean encode)
+			throws Exception {
+		return sendRequest(RequestMethod.POST, url, (Map<String, Object>) params, sign, encode);
+	}
+
+	/**
+	 * 发送Post请求,直接将List类型放入其中
+	 *
+	 * @param postUrl postUrl
+	 * @param formData formData
+	 * @return String
+	 * @throws Exception Exception
+	 */
+	public static String doPost(String postUrl, String formData) throws Exception {
+		HttpClient httpClient = new DefaultHttpClient();
+		HttpPost post = new HttpPost(postUrl);
+		StringEntity postingString = new StringEntity(formData,  HTTP.UTF_8);
+		post.setEntity(postingString);
+		post.setHeader("Content-type", "application/json");
+		HttpResponse response = httpClient.execute(post);
+		String content = EntityUtils.toString(response.getEntity());
+		return content;
+	}
+
+	/**
+	 * 发送DELETE请求
+	 * 
+	 * @param url url
+	 * @param params params
+	 * 
+	 * @return Response
+	 * @throws Exception Exception
+	 */
+	public static Response sendDeleteRequest(String url, Map<String, ?> params) throws Exception {
+		return sendDeleteRequest(url, params, false);
+	}
+
+	/**
+	 * 发送DELETE请求
+	 * 
+	 * @param url url
+	 * @param params params
+	 * @param sign
+	 *            是否发送签名
+	 * @return Response
+	 * @throws Exception Exception
+	 */
+	@SuppressWarnings("unchecked")
+	public static Response sendDeleteRequest(String url, Map<String, ?> params, boolean sign) throws Exception {
+		return sendRequest(RequestMethod.DELETE, url, (Map<String, Object>) params, sign, false);
+	}
+
+	/**
+	 * 发起http请求
+	 * 
+	 * @param method
+	 *            请求方法GET、POST、PUT、DELETE
+	 * @param url
+	 *            请求链接
+	 * @param params
+	 *            参数
+	 * @param sign
+	 *            是否签名
+	 * @param encode encode
+	 * @return Response
+	 * @throws Exception Exception
+	 */
+	public static Response sendRequest(RequestMethod method, String url, Map<String, Object> params, boolean sign,
+			boolean encode) throws Exception {
+		switch (method) {
+		case GET:
+			return sendHttpUriRequest(new HttpGet(getRequestUrl(url, params, sign)));
+		case POST:
+			return sendHttpEntityEnclosingRequest(new HttpPost(getRequestUrl(url, sign)), params, encode);
+		case PUT:
+			return sendHttpEntityEnclosingRequest(new HttpPut(getRequestUrl(url, sign)), params, encode);
+		case DELETE:
+			return sendHttpUriRequest(new HttpDelete(getRequestUrl(url, params, sign)));
+		default:
+			return sendHttpUriRequest(new HttpGet(getRequestUrl(url, params, sign)));
+		}
+	}
+
+	/**
+	 * 发起GET、DELETE请求
+	 * 
+	 * @param request request
+	 * @return Response
+	 */
+	public static Response sendHttpUriRequest(HttpRequestBase request) throws Exception {
+		CloseableHttpClient httpClient = HttpClients.createDefault();
+		CloseableHttpResponse response = null;
+		try {
+			response = httpClient.execute(request);
+			return Response.getResponse(response);
+		} finally {
+			try {
+				httpClient.close();
+			} catch (IOException e) {
+			}
+			if (response != null) {
+				try {
+					response.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+	}
+
+	/**
+	 * 发起POST、PUT请求
+	 * 
+	 * @param request request
+	 * @param params params
+	 * @return Response
+	 */
+	public static Response sendHttpEntityEnclosingRequest(HttpEntityEnclosingRequestBase request,
+			Map<String, Object> params, boolean encode) throws Exception {
+		CloseableHttpClient httpClient = HttpClients.createDefault();
+		CloseableHttpResponse response = null;
+		try {
+			if (!encode) {
+				request.setEntity(new StringEntity(JSON.toJSONString(params), ContentType.APPLICATION_JSON));
+			} else {
+				List<NameValuePair> nvps = new ArrayList<NameValuePair>();
+				if (params != null && !params.isEmpty()) {
+					Set<Entry<String, Object>> entrys = params.entrySet();
+					for (Entry<String, Object> entry : entrys) {
+						Object entryValue = entry.getValue();
+						String entryValueStr = null;
+						if (entryValue instanceof String) {
+							entryValueStr = entryValue.toString();
+						} else {
+							entryValueStr = JSON.toJSONString(entry.getValue());
+						}
+						nvps.add(new BasicNameValuePair(entry.getKey(), URLEncoder.encode(entryValueStr, "UTF-8")));
+					}
+				}
+				request.setEntity(new UrlEncodedFormEntity(nvps));
+			}
+			response = httpClient.execute(request);
+			return Response.getResponse(response);
+		} finally {
+			request.releaseConnection();
+			try {
+				httpClient.close();
+			} catch (IOException e) {
+			}
+			if (response != null) {
+				try {
+					response.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+	}
+
+	/**
+	 * 将请求参数添加到链接中
+	 *
+	 * @param url
+	 * @param params
+	 * @param sign
+	 *            是否签名
+	 * @return
+	 * @throws UnsupportedEncodingException
+	 */
+	public static String getRequestUrl(String url, Map<String, Object> params, boolean sign)
+			throws UnsupportedEncodingException {
+		StringBuilder buf = new StringBuilder(url);
+		if (url.indexOf("?") == -1)
+			buf.append("?");
+		else if (!url.endsWith("&"))
+			buf.append("&");
+		// 如果是GET请求,则请求参数在URL中
+		if (params != null && !params.isEmpty()) {
+			Set<Entry<String, Object>> entrys = params.entrySet();
+			for (Entry<String, Object> entry : entrys) {
+				buf.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue().toString(), "UTF-8"))
+						.append("&");
+			}
+		}
+		if (sign) {
+			// 加时间戳,保持相同请求每次签名均不一样
+			buf.append("_timestamp=").append(System.currentTimeMillis());
+			String message = buf.toString();
+			// 对请求串进行签名
+			buf.append("&_signature=").append(HmacUtils.encode(message));
+		} else
+			buf.deleteCharAt(buf.length() - 1);
+		return buf.toString();
+	}
+
+	/**
+	 * 将签名信息添加到链接中
+	 * 
+	 * @param url
+	 * @param sign
+	 *            是否签名
+	 * @return
+	 */
+	public static String getRequestUrl(String url, boolean sign) {
+		try {
+			return getRequestUrl(url, null, sign);
+		} catch (UnsupportedEncodingException e) {
+		}
+		return null;
+	}
+
+	/**
+	 * 将输入流转为字节数组
+	 * 
+	 * @param inStream
+	 * @return
+	 */
+	public static byte[] read2Byte(InputStream inStream) throws Exception {
+		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
+		byte[] buffer = new byte[1024];
+		int len = 0;
+		while ((len = inStream.read(buffer)) != -1) {
+			outSteam.write(buffer, 0, len);
+		}
+		outSteam.close();
+		inStream.close();
+		return outSteam.toByteArray();
+	}
+
+	/**
+	 * 将输入流转为字符串
+	 * 
+	 * @param inStream
+	 * @return
+	 */
+	public static String read2String(InputStream inStream) throws Exception {
+		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
+		byte[] buffer = new byte[1024];
+		int len = 0;
+		while ((len = inStream.read(buffer)) != -1) {
+			outSteam.write(buffer, 0, len);
+		}
+		try {
+			outSteam.close();
+			inStream.close();
+		} catch (Exception e) {
+
+		}
+		return new String(outSteam.toByteArray(), "UTF-8");
+	}
+
+	/**
+	 * 发送xml数据
+	 * 
+	 * @param path
+	 *            请求地址
+	 * @param xml
+	 *            xml数据
+	 * @param encoding
+	 *            编码
+	 * @return
+	 */
+	public static byte[] postXml(String path, String xml, String encoding) throws Exception {
+		byte[] data = xml.getBytes(encoding);
+		URL url = new URL(path);
+		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+		conn.setRequestMethod("POST");
+		conn.setDoOutput(true);
+		conn.setRequestProperty("Content-Type", "text/xml; charset=" + encoding);
+		conn.setRequestProperty("Content-Length", String.valueOf(data.length));
+		conn.setConnectTimeout(5 * 1000);
+		OutputStream outStream = conn.getOutputStream();
+		outStream.write(data);
+		outStream.flush();
+		outStream.close();
+		if (conn.getResponseCode() == HttpStatus.OK.value()) {
+			return read2Byte(conn.getInputStream());
+		}
+		return null;
+	}
+
+	/**
+	 * http上传文件
+	 * 
+	 * @param postUrl
+	 *            请求地址
+	 * @param filePath
+	 *            附件路径
+	 * @param params
+	 *            参数
+	 * @return
+	 * @throws Exception Exception
+	 * @throws IOException IOException
+	 * @throws IllegalStateException IllegalStateException
+	 */
+	public static Response upload(String postUrl, String filePath, Map<String, String> params)
+			throws IllegalStateException, IOException, Exception {
+		CloseableHttpClient httpClient = null;
+		CloseableHttpResponse response = null;
+		try {
+			httpClient = HttpClients.createDefault();
+			HttpPost httpPost = new HttpPost(postUrl);
+			FileBody fileBody = new FileBody(new File(filePath));
+			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+			builder.addPart("file", fileBody);
+			if (params != null) {
+				for (String paramKey : params.keySet()) {
+					StringBody body = new StringBody(params.get(paramKey), ContentType.create("text/plain",
+							Consts.UTF_8));
+					builder.addPart(paramKey, body);
+				}
+			}
+			HttpEntity reqEntity = builder.build();
+			httpPost.setEntity(reqEntity);
+			response = httpClient.execute(httpPost);
+		} finally {
+			try {
+				if (response != null) {
+					response.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			try {
+				if (httpClient != null) {
+					httpClient.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+		return Response.getResponse(response);
+	}
+
+	/**
+	 * 下载
+	 * 
+	 * @param postUrl
+	 * @return
+	 * @throws ClientProtocolException
+	 * @throws IOException
+	 */
+	public static InputStream download(String postUrl) throws ClientProtocolException, IOException {
+		CloseableHttpClient httpClient = HttpClients.createDefault();
+		HttpGet httpGet = new HttpGet(postUrl);
+		CloseableHttpResponse response = httpClient.execute(httpGet);
+		return response.getEntity().getContent();
+	}
+
+	/**
+	 * 获取请求客户端的IP地址
+	 * 
+	 * @param request
+	 * @return
+	 */
+	public static String getIpAddr(HttpServletRequest request) {
+		String ip = request.getHeader("x-forwarded-for");
+		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+			ip = request.getHeader("Proxy-Client-IP");
+		}
+		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+			ip = request.getHeader("WL-Proxy-Client-IP");
+		}
+		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+			ip = request.getHeader("HTTP_CLIENT_IP");
+		}
+		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+		}
+		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+			ip = request.getRemoteAddr();
+		}
+		return ip;
+	}
+	
+	/**
+	 * POST发送
+	 * 
+	 * @param url
+	 * @param data
+	 */
+	public static String post(String url, String data) throws Exception {
+		URL urls = new URL(url);
+		HttpURLConnection http = (HttpURLConnection) urls.openConnection();
+		http.setRequestMethod("POST");
+		http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+		http.setDoOutput(true);
+		http.setDoInput(true);
+		System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
+		System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
+		http.connect();
+		OutputStream os = http.getOutputStream();
+		os.write(data.getBytes("UTF-8"));// 传入参数
+		os.flush();
+		os.close();
+		// 从服务器读取响应
+		String encoding = http.getContentEncoding();
+		if (encoding == null)
+			encoding = "UTF-8";
+		return StreamUtils.copyToString(http.getInputStream(), Charset.forName(encoding));
+	}
+
+	public static class Response {
+		private int statusCode;
+		private String responseText;
+		private HttpResponse response;
+
+		public int getStatusCode() {
+			return statusCode;
+		}
+
+		public void setStatusCode(int statusCode) {
+			this.statusCode = statusCode;
+		}
+
+		public String getResponseText() {
+			return responseText;
+		}
+
+		public void setResponseText(String responseText) {
+			this.responseText = responseText;
+		}
+
+		public HttpResponse getResponse() {
+			return response;
+		}
+
+		public void setResponse(HttpResponse response) {
+			this.response = response;
+		}
+
+		public Response() {
+		}
+
+		public Response(HttpResponse response) throws IllegalStateException, IOException, Exception {
+			this.statusCode = response.getStatusLine().getStatusCode();
+			this.responseText = HttpUtil.read2String(response.getEntity().getContent());
+			this.response = response;
+		}
+
+		public static Response getResponse(HttpResponse response) throws IllegalStateException, IOException, Exception {
+			if (response != null)
+				return new Response(response);
+			return null;
+		}
+	}
+}

+ 55 - 0
src/main/java/com/uas/ps/core/util/IpHelper.java

@@ -0,0 +1,55 @@
+package com.uas.ps.core.util;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.regex.Pattern;
+
+/**
+ * <p>
+ * 获取IP地址类
+ * </p>
+ * 
+ */
+public class IpHelper {
+
+	/**
+	 * 获取客户端IP
+	 * 
+	 * @param request
+	 * @return
+	 */
+	public static String getIp(HttpServletRequest request) {
+		String ipAddress = null;
+		ipAddress = request.getHeader("X-Forwarded-For");
+		if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+			ipAddress = request.getHeader("Proxy-Client-IP");
+		}
+		if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+			ipAddress = request.getHeader("WL-Proxy-Client-IP");
+		}
+		if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+			ipAddress = request.getRemoteAddr();
+		}
+		// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
+		if (ipAddress != null && ipAddress.length() > 15) {
+			if (ipAddress.indexOf(",") > 0) {
+				ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
+			}
+		}
+		// window7系统下,用localhost访问时,ip会变成0:0:0:0:0:0:0:1
+		if (ipAddress != null && "0:0:0:0:0:0:0:1".equals(ipAddress)) {
+			ipAddress = "127.0.0.1";
+		}
+		return ipAddress;
+	}
+
+	/**
+	 * 判断指定的ip地址是否在局域网内
+	 * 
+	 * @param ipAddress
+	 * @return
+	 */
+	public static boolean isLAN(String ipAddress) {
+		return Pattern.matches("^((192.168.)|(10.)|(172.16)|(127.0))+[0-9.]+$", ipAddress);
+	}
+
+}

+ 161 - 0
src/main/java/com/uas/ps/core/util/ObjectUtils.java

@@ -0,0 +1,161 @@
+package com.uas.ps.core.util;
+
+import java.io.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 对象工具类
+ *
+ * @author sunyj
+ * @since 2017年9月1日 下午3:54:26
+ */
+public class ObjectUtils {
+
+    /**
+     * 判断是否为 null、空数组、空串或者空集合
+     *
+     * @param obj 对象
+     * @return 是否为 null、空数组、空串或者空集合
+     */
+    public static boolean isEmpty(Object obj) {
+        if (obj == null) {
+            return true;
+        }
+        if (obj.getClass().isArray()) {
+            if (obj instanceof long[]) {
+                return ArrayUtils.isEmpty((long[]) obj);
+            } else if (obj instanceof int[]) {
+                return ArrayUtils.isEmpty((int[]) obj);
+            } else if (obj instanceof short[]) {
+                return ArrayUtils.isEmpty((short[]) obj);
+            } else if (obj instanceof byte[]) {
+                return ArrayUtils.isEmpty((byte[]) obj);
+            } else if (obj instanceof char[]) {
+                return ArrayUtils.isEmpty((char[]) obj);
+            } else if (obj instanceof boolean[]) {
+                return ArrayUtils.isEmpty((boolean[]) obj);
+            } else if (obj instanceof float[]) {
+                return ArrayUtils.isEmpty((float[]) obj);
+            } else if (obj instanceof double[]) {
+                return ArrayUtils.isEmpty((double[]) obj);
+            }
+            return ArrayUtils.isEmpty((Object[]) obj);
+        }
+        return (obj instanceof String && StringUtils.isEmpty(obj))
+                || (obj instanceof Collection && CollectionUtils.isEmpty((Collection<?>) obj))
+                || (obj instanceof Map && CollectionUtils.isEmpty((Map<?, ?>) obj));
+    }
+
+    /**
+     * 将对象转为 String
+     *
+     * @param obj 对象
+     * @return 转换的 String
+     */
+    public static String toString(Object obj) {
+        if (obj == null) {
+            return "";
+        }
+        if (obj instanceof String) {
+            return (String) obj;
+        }
+        if (obj.getClass().isArray()) {
+            if (obj instanceof long[]) {
+                return Arrays.toString((long[]) obj);
+            } else if (obj instanceof int[]) {
+                return Arrays.toString((int[]) obj);
+            } else if (obj instanceof short[]) {
+                return Arrays.toString((short[]) obj);
+            } else if (obj instanceof byte[]) {
+                return Arrays.toString((byte[]) obj);
+            } else if (obj instanceof char[]) {
+                return Arrays.toString((char[]) obj);
+            } else if (obj instanceof boolean[]) {
+                return Arrays.toString((boolean[]) obj);
+            } else if (obj instanceof float[]) {
+                return Arrays.toString((float[]) obj);
+            } else if (obj instanceof double[]) {
+                return Arrays.toString((double[]) obj);
+            }
+            return Arrays.toString((Object[]) obj);
+        }
+        return obj.toString();
+    }
+
+    /**
+     * 深克隆对象
+     *
+     * @param t 要克隆的对象
+     * @return 克隆得到的对象
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends Serializable> T clone(T t)
+            throws IOException, ClassNotFoundException, NotSerializableException {
+        if (t == null) {
+            return null;
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        new ObjectOutputStream(out).writeObject(t);
+        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+        return (T) in.readObject();
+    }
+
+    /**
+     * 深克隆集合对象
+     *
+     * @param collection 要克隆的对象
+     * @return 克隆得到的对象
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Collection<T> clone(Collection<T> collection) throws InstantiationException,
+            IllegalAccessException, NotSerializableException, ClassNotFoundException, IOException {
+        if (collection == null) {
+            return null;
+        }
+        Collection<T> result = collection.getClass().newInstance();
+        for (T t : collection) {
+            if (t instanceof Serializable) {
+                result.add((T) clone((Serializable) t));
+            } else if (t instanceof Collection) {
+                result.add((T) clone((Collection<?>) t));
+            } else if (t instanceof Map) {
+                result.add((T) clone((Map<String, ?>) t));
+            } else {
+                throw new IllegalArgumentException("未实现 Serializable 接口");
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 深克隆 Map 对象
+     *
+     * @param map 要克隆的对象
+     * @return 克隆得到的对象
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Map<String, T> clone(Map<String, T> map) throws InstantiationException, IllegalAccessException,
+            NotSerializableException, ClassNotFoundException, IOException {
+        if (map == null) {
+            return null;
+        }
+        Map<String, T> result = map.getClass().newInstance();
+        Set<Map.Entry<String, T>> entrySet = map.entrySet();
+        for (Map.Entry<String, T> entry : entrySet) {
+            T value = entry.getValue();
+            if (value instanceof Serializable) {
+                result.put(entry.getKey(), (T) clone((Serializable) value));
+            } else if (value instanceof Collection) {
+                result.put(entry.getKey(), (T) clone((Collection<?>) value));
+            } else if (value instanceof Map) {
+                result.put(entry.getKey(), (T) clone((Map<String, ?>) value));
+            } else {
+                throw new IllegalArgumentException("未实现 Serializable 接口");
+            }
+        }
+        return result;
+    }
+}

+ 92 - 0
src/main/java/com/uas/ps/core/util/StringUtils.java

@@ -0,0 +1,92 @@
+package com.uas.ps.core.util;
+
+/**
+ * @author sunyj
+ * @since 2017年5月25日 上午11:09:36
+ */
+public class StringUtils {
+
+    public static boolean isEmpty(Object str) {
+        return (str == null || !hasText(str.toString()));
+    }
+
+    /**
+     * Check that the given {@code CharSequence} is neither {@code null} nor
+     * of length 0.
+     * <p>Note: this method returns {@code true} for a {@code CharSequence}
+     * that purely consists of whitespace.
+     * <p><pre class="code">
+     * StringUtils.hasLength(null) = false
+     * StringUtils.hasLength("") = false
+     * StringUtils.hasLength(" ") = true
+     * StringUtils.hasLength("Hello") = true
+     * </pre>
+     *
+     * @param str the {@code CharSequence} to check (may be {@code null})
+     * @return {@code true} if the {@code CharSequence} is not {@code null} and has length
+     * @see #hasText(String)
+     */
+    public static boolean hasLength(CharSequence str) {
+        return (str != null && str.length() > 0);
+    }
+
+    /**
+     * Check that the given {@code String} is neither {@code null} nor of length 0.
+     * <p>Note: this method returns {@code true} for a {@code String} that
+     * purely consists of whitespace.
+     *
+     * @param str the {@code String} to check (may be {@code null})
+     * @return {@code true} if the {@code String} is not {@code null} and has length
+     * @see #hasLength(CharSequence)
+     * @see #hasText(String)
+     */
+    public static boolean hasLength(String str) {
+        return hasLength((CharSequence) str);
+    }
+
+    /**
+     * Check whether the given {@code CharSequence} contains actual <em>text</em>.
+     * <p>More specifically, this method returns {@code true} if the
+     * {@code CharSequence} is not {@code null}, its length is greater than
+     * 0, and it contains at least one non-whitespace character.
+     * <p><pre class="code">
+     * StringUtils.hasText(null) = false
+     * StringUtils.hasText("") = false
+     * StringUtils.hasText(" ") = false
+     * StringUtils.hasText("12345") = true
+     * StringUtils.hasText(" 12345 ") = true
+     * </pre>
+     *
+     * @param str the {@code CharSequence} to check (may be {@code null})
+     * @return {@code true} if the {@code CharSequence} is not {@code null},
+     * its length is greater than 0, and it does not contain whitespace only
+     * @see Character#isWhitespace
+     */
+    public static boolean hasText(CharSequence str) {
+        if (!hasLength(str)) {
+            return false;
+        }
+        int strLen = str.length();
+        for (int i = 0; i < strLen; i++) {
+            if (!Character.isWhitespace(str.charAt(i))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check whether the given {@code String} contains actual <em>text</em>.
+     * <p>More specifically, this method returns {@code true} if the
+     * {@code String} is not {@code null}, its length is greater than 0,
+     * and it contains at least one non-whitespace character.
+     *
+     * @param str the {@code String} to check (may be {@code null})
+     * @return {@code true} if the {@code String} is not {@code null}, its
+     * length is greater than 0, and it does not contain whitespace only
+     * @see #hasText(CharSequence)
+     */
+    public static boolean hasText(String str) {
+        return hasText((CharSequence) str);
+    }
+}