Pārlūkot izejas kodu

调问网问卷系统开源初始提交

KeYuan 8 gadi atpakaļ
revīzija
26f97c417d
100 mainītis faili ar 10917 papildinājumiem un 0 dzēšanām
  1. 29 0
      .gitignore
  2. 84 0
      README.md
  3. 6 0
      bin/install-lose-jar.sh
  4. BIN
      lib/QRCode.jar
  5. BIN
      lib/spssw-1.66.jar
  6. BIN
      lib/xssProtect-0.1.jar
  7. 588 0
      pom.xml
  8. 133 0
      src/main/java/com/baidu/ueditor/ActionEnter.java
  9. 272 0
      src/main/java/com/baidu/ueditor/ConfigManager.java
  10. 157 0
      src/main/java/com/baidu/ueditor/CopyOfPathFormat.java
  11. 24 0
      src/main/java/com/baidu/ueditor/Encoder.java
  12. 179 0
      src/main/java/com/baidu/ueditor/PathFormat.java
  13. 42 0
      src/main/java/com/baidu/ueditor/define/ActionMap.java
  14. 5 0
      src/main/java/com/baidu/ueditor/define/ActionState.java
  15. 77 0
      src/main/java/com/baidu/ueditor/define/AppInfo.java
  16. 90 0
      src/main/java/com/baidu/ueditor/define/BaseState.java
  17. 31 0
      src/main/java/com/baidu/ueditor/define/FileType.java
  18. 20 0
      src/main/java/com/baidu/ueditor/define/MIMEType.java
  19. 112 0
      src/main/java/com/baidu/ueditor/define/MultiState.java
  20. 18 0
      src/main/java/com/baidu/ueditor/define/State.java
  21. 112 0
      src/main/java/com/baidu/ueditor/hunter/CopyOfFileManager.java
  22. 215 0
      src/main/java/com/baidu/ueditor/hunter/FileManager.java
  23. 135 0
      src/main/java/com/baidu/ueditor/hunter/ImageHunter.java
  24. 54 0
      src/main/java/com/baidu/ueditor/upload/Base64Uploader.java
  25. 110 0
      src/main/java/com/baidu/ueditor/upload/BinaryUploader.java
  26. 52 0
      src/main/java/com/baidu/ueditor/upload/CopyOfBase64Uploader.java
  27. 98 0
      src/main/java/com/baidu/ueditor/upload/CopyOfBinaryUploader.java
  28. 155 0
      src/main/java/com/baidu/ueditor/upload/CopyOfStorageManager.java
  29. 247 0
      src/main/java/com/baidu/ueditor/upload/StorageManager.java
  30. 29 0
      src/main/java/com/baidu/ueditor/upload/Uploader.java
  31. 38 0
      src/main/java/com/key/common/CheckType.java
  32. 65 0
      src/main/java/com/key/common/QuType.java
  33. 50 0
      src/main/java/com/key/common/YesnoOption.java
  34. 131 0
      src/main/java/com/key/common/base/action/CrudActionSupport.java
  35. 123 0
      src/main/java/com/key/common/base/action/JcaptchaAction.java
  36. 259 0
      src/main/java/com/key/common/base/action/UploadAction.java
  37. 18 0
      src/main/java/com/key/common/base/dao/UserDao.java
  38. 29 0
      src/main/java/com/key/common/base/dao/UserDaoImpl.java
  39. 39 0
      src/main/java/com/key/common/base/entity/IdEntity.java
  40. 34 0
      src/main/java/com/key/common/base/entity/IdLongEntity.java
  41. 76 0
      src/main/java/com/key/common/base/entity/Tracker.java
  42. 14 0
      src/main/java/com/key/common/base/entity/TrackerConstants.java
  43. 248 0
      src/main/java/com/key/common/base/entity/User.java
  44. 185 0
      src/main/java/com/key/common/base/service/AccountManager.java
  45. 14 0
      src/main/java/com/key/common/dao/BaseDao.java
  46. 14 0
      src/main/java/com/key/common/dao/BaseDaoImpl.java
  47. 531 0
      src/main/java/com/key/common/dao/HibernateDao.java
  48. 135 0
      src/main/java/com/key/common/dao/IHibernateDao.java
  49. 213 0
      src/main/java/com/key/common/dao/ISimpleHibernateDao.java
  50. 349 0
      src/main/java/com/key/common/dao/SimpleHibernateDao.java
  51. 29 0
      src/main/java/com/key/common/exception/ServiceException.java
  52. 161 0
      src/main/java/com/key/common/plugs/aliyun/AliyunOSS.java
  53. 159 0
      src/main/java/com/key/common/plugs/baiduyun/BaiduBOS.java
  54. 59 0
      src/main/java/com/key/common/plugs/data/mysql/MySQLDatabaseBackup.java
  55. 79 0
      src/main/java/com/key/common/plugs/email/Email.java
  56. 16 0
      src/main/java/com/key/common/plugs/email/MailService.java
  57. 70 0
      src/main/java/com/key/common/plugs/freemarker/FreeMarkertUtil.java
  58. 26 0
      src/main/java/com/key/common/plugs/freemarker/FreemarkerTest.java
  59. 14 0
      src/main/java/com/key/common/plugs/ipaddr/IPEntry.java
  60. 661 0
      src/main/java/com/key/common/plugs/ipaddr/IPSeeker.java
  61. 129 0
      src/main/java/com/key/common/plugs/ipaddr/IPService.java
  62. 18 0
      src/main/java/com/key/common/plugs/ipaddr/NsLookup.java
  63. 100 0
      src/main/java/com/key/common/plugs/ipaddr/Utils.java
  64. BIN
      src/main/java/com/key/common/plugs/ipaddr/qqwry.dat
  65. 255 0
      src/main/java/com/key/common/plugs/itextpdf/Demo4URL2PDF.java
  66. 255 0
      src/main/java/com/key/common/plugs/itextpdf/Demo5URL2PDF.java
  67. 119 0
      src/main/java/com/key/common/plugs/itextpdf/ItextpdfTest.java
  68. 99 0
      src/main/java/com/key/common/plugs/itextpdf/PDFUtil.java
  69. 84 0
      src/main/java/com/key/common/plugs/itextpdf/WordTest.java
  70. 100 0
      src/main/java/com/key/common/plugs/jcaptcha/CaptchaEngineEx.java
  71. 38 0
      src/main/java/com/key/common/plugs/jms/advanced/AdvancedNotifyMessageListener.java
  72. 83 0
      src/main/java/com/key/common/plugs/jms/advanced/AdvancedNotifyMessageProducer.java
  73. 42 0
      src/main/java/com/key/common/plugs/jms/jms/InvokeMessage.java
  74. 29 0
      src/main/java/com/key/common/plugs/jms/jms/InvokeMessageConsumer.java
  75. 85 0
      src/main/java/com/key/common/plugs/jms/jms/InvokeMessageConverter.java
  76. 49 0
      src/main/java/com/key/common/plugs/jms/jms/InvokeMessageProducer.java
  77. 64 0
      src/main/java/com/key/common/plugs/jms/simple/NotifyMessageListener.java
  78. 116 0
      src/main/java/com/key/common/plugs/jms/simple/NotifyMessageProducer.java
  79. 81 0
      src/main/java/com/key/common/plugs/mapper/CollectionMapper.java
  80. 96 0
      src/main/java/com/key/common/plugs/mapper/ObjectMapper.java
  81. 210 0
      src/main/java/com/key/common/plugs/page/Page.java
  82. 215 0
      src/main/java/com/key/common/plugs/page/PageRequest.java
  83. 170 0
      src/main/java/com/key/common/plugs/page/PropertyFilter.java
  84. 157 0
      src/main/java/com/key/common/plugs/security/FormAuthenticationWithLockFilter.java
  85. 130 0
      src/main/java/com/key/common/plugs/security/LoginAction.java
  86. 21 0
      src/main/java/com/key/common/plugs/security/MyDefaultWebSecurityManager.java
  87. 100 0
      src/main/java/com/key/common/plugs/security/ShiroDbRealm.java
  88. 29 0
      src/main/java/com/key/common/plugs/spss/demo/CSVExportUtil.java
  89. 33 0
      src/main/java/com/key/common/plugs/spss/demo/csv/DemoCsv.java
  90. 7 0
      src/main/java/com/key/common/plugs/spss/demo/csv/demo.csv
  91. 113 0
      src/main/java/com/key/common/plugs/spss/demo/java/Demo.java
  92. 34 0
      src/main/java/com/key/common/plugs/spss/demo/xml/DemoXml.java
  93. 59 0
      src/main/java/com/key/common/plugs/spss/demo/xml/demo.xml
  94. 39 0
      src/main/java/com/key/common/plugs/xss/XssFilter.java
  95. 143 0
      src/main/java/com/key/common/plugs/xss/XssHttpWrapper.java
  96. 35 0
      src/main/java/com/key/common/service/BaseService.java
  97. 76 0
      src/main/java/com/key/common/service/BaseServiceImpl.java
  98. 441 0
      src/main/java/com/key/common/utils/AssertUtils.java
  99. 79 0
      src/main/java/com/key/common/utils/CookieUtils.java
  100. 71 0
      src/main/java/com/key/common/utils/DiaowenProperty.java

+ 29 - 0
.gitignore

@@ -0,0 +1,29 @@
+# maven ignore
+target
+classes
+/src/main/webapp/dcpic/
+# eclipse ignore
+.settings/
+.project
+.classpath
+catalina.*/
+# idea ignore
+.idea/
+*.ipr
+*.iml
+*.iws
+# temp ignore
+*.log
+*.cache
+*.diff
+*.patch
+*.tmp
+# system ignore
+.DS_Store
+Thumbs.db
+# package ignore (optional)
+# *.jar
+# *.war
+# *.zip
+# *.tar
+# *.tar.gz

+ 84 - 0
README.md

@@ -0,0 +1,84 @@
+# DWSurvey 调问问卷系统
+
+DWSurvey是一款方便、高效、实用的调研问卷系统,一款基于 JAVA WEB 的开源问卷表单系统。
+
+## 演示地址
+
+[http://www.diaowen.com](http://www.diaowen.com)
+
+用户名:service@diaowen  密码: 123456
+
+## 安装
+
+因为DWSurvey是基于JAVA WEB实现,所以安装与一般的JAVA WEB程序无异,配置好数据库地址就可以正常使用。
+
+** 安装说明 **
+
+	服务器必须安装由 JAVA 1.6+、MySQL、Apache Tomcat 构成的环境
+
+** 配置说明 **
+
+配置文件地址
+
+conf/application.properties
+
+	#database settings
+	jdbc.url=jdbc:mysql://localhost:3306/diaowen?useUnicode=true&characterEncoding=utf8
+	jdbc.username=root
+	jdbc.password=123456,.
+
+分别修改```jdbc.url、jdbc.username、jdbc.password```
+
+** 启动访问 **
+
+配置完成后,启动服务在浏览器中输入如```localhost:8080/dwsurvey```相应的地址看到登录页面,表示已经安装成功。
+
+如下图
+
+## 特色
+
+** 全新体验、流程简单 **
+
+![pic](/resources/install/dwsurvey-git-1.png)
+
+以一种全新的设计体验,告别繁琐的设计流程,通过简单有趣的方式,轻轻松松完成问卷设计,多种问卷样式模板选择,只为显现更精美的表单问卷.
+
+** 丰富的题型 **
+
+丰富的题型支持,通过拖拽即可完成题目选择,并可以随意拖动其位置,还可置入所需图片、企业LOGO、设置答题逻辑,一份优美的问卷就是这么简单。
+
+** 问卷表单静态化 **
+
+对于问卷表单系统,因为所有的表单字段都是后台数据库来维护,所以对于每一次答卷请求,如果都从后端数据库去取每一题及选项的话,必定会对性能造成不小影响。
+
+所以在发布的表单问卷时会对数据进行的页面静态化,生成一个真实的表单存档。
+
+## 有问题怎么办?
+
+对于调问网问卷系统安装及使用的问题,可以在用户交流群里,向作者或其它同学提问。
+
+```调问网交流QQ群:198635495 ```
+
+## 开源协议
+
+DWSurvey以宽通用公共许可证LGPL3.0为开源协议,更好的支持商业使用环境!
+
+- - -
+
+## 关于调问网
+
+没事喜欢瞎折腾,业余时间也想做点有意思的事情,同时对产品也比较感兴趣,一翻调研之后就决定来做个问卷系统。
+于是便利用业余时间来做这款问卷表单平台,因为在2012的时候,国内的问卷系统都还比较初级,问卷设计流程复杂,页面也不美观。
+所以就开始边调研、边画原型、边写前后端代码,最初的想法是一定要好用美观,在这之后的一年里就不断的设计开发,前前后后修改过3个大版本,现在开源的3.0版是在2013年9月份完成的。
+
+- - -
+
+## 作者
+
+ 柯远 ```keyuan258@gmail.com```
+
+ ![pic](/resources/install/FF270C289E5AC672250B797A913AEE47.png)
+
+ ** 谢谢您的支持 **
+
+ 觉得不错就点下右上角的star吧,随时关注我们的动态,非常感谢!

+ 6 - 0
bin/install-lose-jar.sh

@@ -0,0 +1,6 @@
+#!/bin/sh
+#可直接执行
+echo [信息] 安装中央仓库缺失jar。
+mvn install:install-file -Dfile=../lib/QRCode.jar -DgroupId=net.qrcode -DartifactId=qrcode -Dversion=1.0 -Dpackaging=jar
+mvn install:install-file -Dfile=../lib/spssw-1.66.jar -DgroupId=net.spssw -DartifactId=spssw -Dversion=1.66 -Dpackaging=jar
+mvn install:install-file -Dfile=../lib/xssProtect-0.1.jar -DgroupId=net.xssprotect -DartifactId=xssprotest -Dversion=1.0 -Dpackaging=jar

BIN
lib/QRCode.jar


BIN
lib/spssw-1.66.jar


BIN
lib/xssProtect-0.1.jar


+ 588 - 0
pom.xml

@@ -0,0 +1,588 @@
+<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>
+  <groupId>keyuan</groupId>
+  <artifactId>diaowen</artifactId>
+  <packaging>war</packaging>
+  <version>0.0.1-SNAPSHOT</version>
+  <name>diaowen Maven Webapp</name>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    
+	<dependency>
+		<groupId>org.apache.geronimo.specs</groupId>
+		<artifactId>geronimo-j2ee-management_1.1_spec</artifactId>
+		<version>1.0.1</version>
+	</dependency>
+
+	<dependency>
+		<groupId>org.apache.geronimo.specs</groupId>
+		<artifactId>geronimo-jms_1.1_spec</artifactId>
+		<version>1.1.1</version>
+	</dependency>
+	<dependency>
+		<groupId>org.hamcrest</groupId>
+		<artifactId>hamcrest-core</artifactId>
+		<version>1.1</version>
+	</dependency>
+	<dependency>
+		<groupId>com.itextpdf</groupId>
+		<artifactId>itextpdf</artifactId>
+		<version>5.4.3</version>
+	</dependency>
+	<dependency>
+		<groupId>com.itextpdf</groupId>
+		<artifactId>itext-asian</artifactId>
+		<version>5.2.0</version>
+	</dependency>
+
+	<!-- https://mvnrepository.com/artifact/com.lowagie/itext -->
+	<dependency>
+		<groupId>com.lowagie</groupId>
+		<artifactId>itext</artifactId>
+		<version>2.0.8</version>
+	</dependency>
+
+	<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
+	<dependency>
+		<groupId>org.jsoup</groupId>
+		<artifactId>jsoup</artifactId>
+		<version>1.7.2</version>
+	</dependency>
+
+	<!-- https://mvnrepository.com/artifact/org.eclipse.birt.runtime.3_7_1/Tidy -->
+	<dependency>
+		<groupId>org.eclipse.birt.runtime.3_7_1</groupId>
+		<artifactId>Tidy</artifactId>
+		<version>1</version>
+	</dependency>
+
+	<!-- https://mvnrepository.com/artifact/com.octo.captcha/jcaptcha-all -->
+	<dependency>
+		<groupId>com.octo.captcha</groupId>
+		<artifactId>jcaptcha-all</artifactId>
+		<version>1.0-RC6</version>
+		<exclusions>
+			<exclusion>
+				<artifactId>spring</artifactId>
+				<groupId>org.springframework</groupId>
+			</exclusion>
+		</exclusions>
+	</dependency>
+
+	<dependency>
+		<groupId>org.sitemesh</groupId>
+		<artifactId>sitemesh</artifactId>
+		<version>3.0-alpha-2</version>
+	</dependency>
+		<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
+	<dependency>
+		<groupId>org.apache.poi</groupId>
+		<artifactId>poi</artifactId>
+		<version>3.7</version>
+	</dependency>
+
+		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
+	<dependency>
+		<groupId>mysql</groupId>
+		<artifactId>mysql-connector-java</artifactId>
+		<version>5.1.6</version>
+	</dependency>
+
+		<!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity -->
+	<dependency>
+		<groupId>org.apache.velocity</groupId>
+		<artifactId>velocity</artifactId>
+		<version>1.7</version>
+	</dependency>
+
+	 <dependency>
+		    <groupId>org.jvnet</groupId>
+		    <artifactId>mimepull</artifactId>
+		    <version>1.4</version>
+	</dependency>
+	
+    <dependency>
+		    <groupId>javax.mail</groupId>
+		    <artifactId>mail</artifactId>
+		    <version>1.4.4</version>
+	</dependency>
+	
+    <dependency>
+		    <groupId>com.itextpdf.tool</groupId>
+		    <artifactId>xmlworker</artifactId>
+		    <version>5.4.3</version>
+	</dependency>
+	
+     <dependency>
+		    <groupId>org.apache.xbean</groupId>
+		    <artifactId>xbean-spring</artifactId>
+		    <version>3.12</version>
+	</dependency>
+    
+     <dependency>
+		    <groupId>org.tuckey</groupId>
+		    <artifactId>urlrewritefilter</artifactId>
+		    <version>4.0.3</version>
+	</dependency>
+    
+    
+     <dependency>
+		    <groupId>org.apache.struts</groupId>
+		    <artifactId>struts2-spring-plugin</artifactId>
+		    <version>${org.struts2.version}</version>
+		</dependency>
+
+     <dependency>
+		    <groupId>org.apache.struts</groupId>
+		    <artifactId>struts2-core</artifactId>
+		    <version>${org.struts2.version}</version>
+		</dependency>
+
+    <dependency>
+		    <groupId>org.apache.struts</groupId>
+		    <artifactId>struts2-convention-plugin</artifactId>
+		    <version>${org.struts2.version}</version>
+		</dependency>
+		
+    <dependency>
+		    <groupId>org.apache.struts</groupId>
+		    <artifactId>struts2-convention-plugin</artifactId>
+		    <version>${org.struts2.version}</version>
+		</dependency>
+
+    <dependency>
+		    <groupId>org.hibernate</groupId>
+		    <artifactId>hibernate-validator</artifactId>
+		    <version>4.2.0.Final</version>
+		</dependency>
+		
+	<dependency>
+		    <groupId>org.hibernate.javax.persistence</groupId>
+		    <artifactId>hibernate-jpa-2.0-api</artifactId>
+		    <version>1.0.1.Final</version>
+		</dependency>
+
+
+	<dependency>
+		    <groupId>org.hibernate</groupId>
+		    <artifactId>hibernate-commons-annotations</artifactId>
+		    <version>3.2.0.Final</version>
+		</dependency>
+		
+    <dependency>
+		    <groupId>org.hibernate</groupId>
+		    <artifactId>hibernate-core</artifactId>
+		    <version>3.6.8.Final</version>
+		</dependency>
+
+		
+		<dependency>
+		    <groupId>com.baidubce</groupId>
+		    <artifactId>bce-java-sdk</artifactId>
+		    <version>0.10.5</version>
+		</dependency>
+		
+		<dependency>
+		    <groupId>com.aliyun.oss</groupId>
+		    <artifactId>aliyun-sdk-oss</artifactId>
+		    <version>2.0.3</version>
+		</dependency>
+		
+		<!-- https://mvnrepository.com/artifact/org.xhtmlrenderer/core-renderer -->
+<dependency>
+    <groupId>org.xhtmlrenderer</groupId>
+    <artifactId>core-renderer</artifactId>
+    <version>R8</version>
+</dependency>
+		
+		<!-- https://mvnrepository.com/artifact/org.json/json -->
+<dependency>
+    <groupId>org.json</groupId>
+    <artifactId>json</artifactId>
+    <version>20160810</version>
+</dependency>
+		
+		
+		<!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-all -->
+<dependency>
+    <groupId>org.apache.activemq</groupId>
+    <artifactId>activemq-all</artifactId>
+    <version>5.8.0</version>
+</dependency>
+		
+		
+     	<dependency>
+		    <groupId>org.apache.activemq</groupId>
+		    <artifactId>activeio-core</artifactId>
+		    <version>3.1.4</version>
+		</dependency>
+		
+		 <!-- Spring -->
+	    <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
+		<dependency>
+		    <groupId>org.springframework</groupId>
+		    <artifactId>spring-web</artifactId>
+		    <version>${org.springframework.version}</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
+		<dependency>
+		    <groupId>org.springframework</groupId>
+		    <artifactId>spring-tx</artifactId>
+		    <version>${org.springframework.version}</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jms -->
+<dependency>
+    <groupId>org.springframework</groupId>
+    <artifactId>spring-jms</artifactId>
+    <version>${org.springframework.version}</version>
+</dependency>
+		
+	    <dependency>
+		    <groupId>org.springframework</groupId>
+		    <artifactId>spring-context</artifactId>
+		    <version>${org.springframework.version}</version>
+		</dependency>
+		<dependency>
+		    <groupId>org.springframework</groupId>
+		    <artifactId>spring-test</artifactId>
+		    <version>${org.springframework.version}</version>
+		</dependency>
+		<dependency>
+		    <groupId>org.springframework</groupId>
+		    <artifactId>spring-context-support</artifactId>
+		    <version>${org.springframework.version}</version>
+		</dependency>
+	   <dependency>
+		    <groupId>org.springframework</groupId>
+		    <artifactId>spring-oxm</artifactId>
+		    <version>${org.springframework.version}</version>
+		</dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${org.springframework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+            <version>${org.springframework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-expression</artifactId>
+            <version>${org.springframework.version}</version>
+        </dependency>
+		
+		<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
+		<dependency>
+		    <groupId>org.springframework</groupId>
+		    <artifactId>spring-aspects</artifactId>
+		    <version>${org.springframework.version}</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
+<dependency>
+    <groupId>org.springframework</groupId>
+    <artifactId>spring-jdbc</artifactId>
+    <version>${org.springframework.version}</version>
+</dependency>
+<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
+<dependency>
+    <groupId>org.springframework</groupId>
+    <artifactId>spring-web</artifactId>
+    <version>${org.springframework.version}</version>
+</dependency>
+<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
+<dependency>
+    <groupId>org.springframework</groupId>
+    <artifactId>spring-orm</artifactId>
+    <version>${org.springframework.version}</version>
+</dependency>
+
+<!-- https://mvnrepository.com/artifact/cglib/cglib-nodep -->
+<dependency>
+    <groupId>cglib</groupId>
+    <artifactId>cglib-nodep</artifactId>
+    <version>2.2.2</version>
+</dependency>
+
+		
+        <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
+		<dependency>
+		    <groupId>commons-logging</groupId>
+		    <artifactId>commons-logging</artifactId>
+		    <version>1.2</version>
+		</dependency>
+
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.4</version>
+        </dependency>
+        
+       <dependency>
+		    <groupId>org.apache.commons</groupId>
+		    <artifactId>commons-lang3</artifactId>
+		    <version>3.4</version>
+		</dependency>
+        
+        <dependency>
+		    <groupId>commons-lang</groupId>
+		    <artifactId>commons-lang</artifactId>
+		    <version>2.6</version>
+		</dependency>
+
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.0.1</version>
+        </dependency>
+    
+	   <dependency>
+		    <groupId>org.apache.httpcomponents</groupId>
+		    <artifactId>httpcore</artifactId>
+		    <version>4.4.5</version>
+		</dependency>
+
+	    <dependency>
+    		<groupId>org.apache.httpcomponents</groupId>
+    		<artifactId>httpclient</artifactId>
+    		<version>4.5.2</version>
+		</dependency>
+		
+		<dependency>
+    		<groupId>org.apache.httpcomponents</groupId>
+    		<artifactId>httpclient-cache</artifactId>
+    		<version>4.5.2</version>
+		</dependency>
+		<dependency>
+    		<groupId>org.apache.httpcomponents</groupId>
+    		<artifactId>httpcore-nio</artifactId>
+    		<version>4.4.5</version>
+		</dependency>
+		
+		<dependency>
+    		<groupId>org.apache.httpcomponents</groupId>
+    		<artifactId>httpmime</artifactId>
+    		<version>4.5.2</version>
+		</dependency>
+		
+		<dependency>
+    		<groupId>com.fasterxml.jackson.core</groupId>
+    		<artifactId>jackson-annotations</artifactId>
+    		<version>2.1.1</version>
+		</dependency>
+		
+		<dependency>
+    		<groupId>com.fasterxml.jackson.core</groupId>
+    		<artifactId>jackson-core</artifactId>
+    		<version>2.1.1</version>
+		</dependency>
+		
+		<dependency>
+    		<groupId>com.fasterxml.jackson.core</groupId>
+    		<artifactId>jackson-databind</artifactId>
+    		<version>2.1.1</version>
+		</dependency>
+		
+		<dependency>
+    		<groupId>com.sun.jersey</groupId>
+    		<artifactId>jersey-client</artifactId>
+    		<version>1.19.1</version>
+		</dependency>
+		
+		
+		<!-- log4j2 -->
+		<!-- https://mvnrepository.com/artifact/log4j/log4j -->
+		<dependency>
+		    <groupId>log4j</groupId>
+		    <artifactId>log4j</artifactId>
+		    <version>1.2.17</version>
+		</dependency>
+
+	  <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
+	  <dependency>
+		  <groupId>org.apache.logging.log4j</groupId>
+		  <artifactId>log4j-core</artifactId>
+		  <version>2.7</version>
+	  </dependency>
+
+		<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
+<dependency>
+    <groupId>org.apache.logging.log4j</groupId>
+    <artifactId>log4j-api</artifactId>
+    <version>2.7</version>
+</dependency>
+		
+        
+         <!--utils-->
+ 		 <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>r09</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>17.0</version>
+        </dependency>
+        
+        
+         <!-- 读取字节码包 -->
+        <dependency>
+            <groupId>org.javassist</groupId>
+            <artifactId>javassist</artifactId>
+            <version>3.15.0-GA</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-all</artifactId>
+            <version>1.2.1</version>
+        </dependency>
+        
+		<dependency>
+		    <groupId>commons-beanutils</groupId>
+		    <artifactId>commons-beanutils</artifactId>
+		    <version>1.9.2</version>
+		</dependency>
+
+		<dependency>
+		    <groupId>net.sf.dozer</groupId>
+		    <artifactId>dozer</artifactId>
+		    <version>5.3.2</version>
+		</dependency>
+		
+		<dependency>
+		    <groupId>net.sf.json-lib</groupId>
+		    <artifactId>json-lib</artifactId>
+		    <version>2.4</version>
+		    <classifier>jdk15</classifier>
+		</dependency>
+
+		<dependency>
+		    <groupId>org.slf4j</groupId>
+		    <artifactId>slf4j-log4j12</artifactId>
+		    <version>1.5.0</version>
+		</dependency>
+		
+		<dependency>
+		    <groupId>javax.servlet</groupId>
+		    <artifactId>jstl</artifactId>
+		    <version>1.2</version>
+		    <type>jar</type>
+		</dependency>
+
+		<dependency>
+		    <groupId>taglibs</groupId>
+		    <artifactId>standard</artifactId>
+		    <version>1.1.2</version>
+		    <type>jar</type>
+		</dependency>
+		
+		   <!-- servlet3 -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>3.0.1</version>
+            <scope>provided</scope>
+        </dependency>
+        
+        <dependency>
+			<groupId>javax.servlet.jsp</groupId>
+			<artifactId>jsp-api</artifactId>
+			<version>2.1</version>
+			<scope>provided</scope>
+	   </dependency>
+	   
+	   <!-- https://mvnrepository.com/artifact/antlr/antlr -->
+<dependency>
+    <groupId>antlr</groupId>
+    <artifactId>antlr</artifactId>
+    <version>2.7.7</version>
+</dependency>
+<!-- https://mvnrepository.com/artifact/org.antlr/antlr-runtime -->
+<dependency>
+    <groupId>org.antlr</groupId>
+    <artifactId>antlr-runtime</artifactId>
+    <version>3.0.1</version>
+</dependency>
+	   
+	   <!-- local lib -->
+		<dependency>
+  			<groupId>net.qrcode</groupId>
+  			<artifactId>qrcode</artifactId>
+  			<version>1.0</version>
+    </dependency>
+	<dependency>
+  			<groupId>net.xssprotect</groupId>
+  			<artifactId>xssprotest</artifactId>
+  			<version>1.0</version>
+    </dependency>
+    
+    <dependency>
+  <groupId>net.spssw</groupId>
+  <artifactId>spssw</artifactId>
+  <version>1.66</version>
+    </dependency>
+
+  </dependencies>
+  <build>
+    <finalName>diaowen</finalName>
+     <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+
+	  <resources>
+		  <resource>
+			  <directory>src/main/java</directory>
+			  <includes>
+				  <include>**/*.dat</include>
+			  </includes>
+			  <filtering>false</filtering>
+		  </resource>
+	  </resources>
+  </build>
+  <properties>
+  	 <org.springframework.version>3.1.2.RELEASE</org.springframework.version>
+	  <org.struts2.version>2.5.10</org.struts2.version>
+     <log4j.version>2.0</log4j.version>
+     <commons.fileupload.version>1.2.1</commons.fileupload.version>
+     <cxf.version>3.0.2</cxf.version>
+  </properties>
+  
+  <profiles>
+    <profile>
+        <id>jdk-1.8</id>
+        <!-- 另外一种激活方式 -->
+        <activation>
+            <activeByDefault>true</activeByDefault>
+            <jdk>1.8</jdk>
+        </activation>
+        <properties>
+            <maven.compiler.source>1.8</maven.compiler.source>
+            <maven.compiler.target>1.8</maven.compiler.target>
+        </properties>
+    </profile>
+</profiles>
+</project>

+ 133 - 0
src/main/java/com/baidu/ueditor/ActionEnter.java

@@ -0,0 +1,133 @@
+package com.baidu.ueditor;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.baidu.ueditor.define.ActionMap;
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.State;
+import com.baidu.ueditor.hunter.FileManager;
+import com.baidu.ueditor.hunter.ImageHunter;
+import com.baidu.ueditor.upload.Uploader;
+
+public class ActionEnter {
+	
+	private HttpServletRequest request = null;
+	
+	private String rootPath = null;
+	private String contextPath = null;
+	
+	private String actionType = null;
+	
+	private ConfigManager configManager = null;
+
+	public ActionEnter ( HttpServletRequest request, String rootPath ) {
+		
+		this.request = request;
+		this.rootPath = rootPath;
+		this.actionType = request.getParameter( "action" );
+		this.contextPath = request.getContextPath();
+		this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, request.getRequestURI() );
+		this.configManager.updateConfig();
+	}
+	
+	public String exec () {
+		
+		String callbackName = this.request.getParameter("callback");
+		
+		if ( callbackName != null ) {
+
+			if ( !validCallbackName( callbackName ) ) {
+				return new BaseState( false, AppInfo.ILLEGAL ).toJSONString();
+			}
+			
+			return callbackName+"("+this.invoke()+");";
+			
+		} else {
+			return this.invoke();
+		}
+
+	}
+	
+	public String invoke() {
+		
+		if ( actionType == null || !ActionMap.mapping.containsKey( actionType ) ) {
+			return new BaseState( false, AppInfo.INVALID_ACTION ).toJSONString();
+		}
+		
+		if ( this.configManager == null || !this.configManager.valid() ) {
+			return new BaseState( false, AppInfo.CONFIG_ERROR ).toJSONString();
+		}
+		
+		State state = null;
+		
+		int actionCode = ActionMap.getType( this.actionType );
+		
+		Map<String, Object> conf = null;
+		
+		try{
+
+			switch ( actionCode ) {
+			
+				case ActionMap.CONFIG:
+					return this.configManager.getAllConfig().toString();
+					
+				case ActionMap.UPLOAD_IMAGE:
+				case ActionMap.UPLOAD_SCRAWL:
+				case ActionMap.UPLOAD_VIDEO:
+				case ActionMap.UPLOAD_FILE:
+					conf = this.configManager.getConfig( actionCode );
+					state = new Uploader( request, conf ).doExec();
+					break;
+					
+				case ActionMap.CATCH_IMAGE:
+					conf = configManager.getConfig( actionCode );
+					String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) );
+					state = new ImageHunter( conf ).capture( list );
+					break;
+					
+				case ActionMap.LIST_IMAGE:
+				case ActionMap.LIST_FILE:
+					conf = configManager.getConfig( actionCode );
+					int start = this.getStartIndex();
+					state = new FileManager( conf ).listFile( start );
+					break;
+					
+			}
+			
+		}catch(Exception e){
+			e.printStackTrace();
+		}
+		
+		return state.toJSONString();
+		
+	}
+	
+	public int getStartIndex () {
+		
+		String start = this.request.getParameter( "start" );
+		
+		try {
+			return Integer.parseInt( start );
+		} catch ( Exception e ) {
+			return 0;
+		}
+		
+	}
+	
+	/**
+	 * callback参数验证
+	 */
+	public boolean validCallbackName ( String name ) {
+		
+		if ( name.matches( "^[a-zA-Z_]+[\\w0-9_]*$" ) ) {
+			return true;
+		}
+		
+		return false;
+		
+	}
+	
+}

+ 272 - 0
src/main/java/com/baidu/ueditor/ConfigManager.java

@@ -0,0 +1,272 @@
+package com.baidu.ueditor;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import com.baidu.ueditor.define.ActionMap;
+import com.key.common.utils.DiaowenProperty;
+import com.key.common.utils.web.InitAppliction;
+
+/**
+ * 配置管理器
+ * @author hancong03@baidu.com
+ *
+ */
+public final class ConfigManager {
+
+	private final String rootPath;
+	private final String originalPath;
+	private final String contextPath;
+	private static final String configFileName = "config.json";
+	private String parentPath = null;
+	private JSONObject jsonConfig = null;
+	// 涂鸦上传filename定义
+	private final static String SCRAWL_FILE_NAME = "scrawl";
+	// 远程图片抓取filename定义
+	private final static String REMOTE_FILE_NAME = "remote";
+	private static boolean UPCONFIG = false;
+	/*
+	 * 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件
+	 */
+	private ConfigManager ( String rootPath, String contextPath, String uri ) throws FileNotFoundException, IOException {
+		
+		rootPath = rootPath.replace( "\\", "/" );
+		
+		this.rootPath = rootPath;
+		this.contextPath = contextPath;
+		
+		if ( contextPath.length() > 0 ) {
+			this.originalPath = this.rootPath + uri.substring( contextPath.length() );
+		} else {
+			this.originalPath = this.rootPath + uri;
+		}
+		
+		this.initEnv();
+		
+	}
+	
+	/**
+	 * 配置管理器构造工厂
+	 * @param rootPath 服务器根路径
+	 * @param contextPath 服务器所在项目路径
+	 * @param uri 当前访问的uri
+	 * @return 配置管理器实例或者null
+	 */
+	public static ConfigManager getInstance ( String rootPath, String contextPath, String uri ) {
+		
+		try {
+			return new ConfigManager(rootPath, contextPath, uri);
+		} catch ( Exception e ) {
+			return null;
+		}
+		
+	}
+	
+	// 验证配置文件加载是否正确
+	public boolean valid () {
+		return this.jsonConfig != null;
+	}
+	
+	public JSONObject getAllConfig () {
+		
+		return this.jsonConfig;
+		
+	}
+	
+	public Map<String, Object> getConfig ( int type ) {
+		
+		Map<String, Object> conf = new HashMap<String, Object>();
+		String savePath = null;
+		
+		switch ( type ) {
+		
+			case ActionMap.UPLOAD_FILE:
+				conf.put( "isBase64", "false" );
+				conf.put( "maxSize", this.jsonConfig.getLong( "fileMaxSize" ) );
+				conf.put( "allowFiles", this.getArray( "fileAllowFiles" ) );
+				conf.put( "fieldName", this.jsonConfig.getString( "fileFieldName" ) );
+				savePath = this.jsonConfig.getString( "filePathFormat" );
+				break;
+				
+			case ActionMap.UPLOAD_IMAGE:
+				conf.put( "isBase64", "false" );
+				conf.put( "maxSize", this.jsonConfig.getLong( "imageMaxSize" ) );
+				conf.put( "allowFiles", this.getArray( "imageAllowFiles" ) );
+				conf.put( "fieldName", this.jsonConfig.getString( "imageFieldName" ) );
+				savePath = this.jsonConfig.getString( "imagePathFormat" );
+				break;
+				
+			case ActionMap.UPLOAD_VIDEO:
+				conf.put( "maxSize", this.jsonConfig.getLong( "videoMaxSize" ) );
+				conf.put( "allowFiles", this.getArray( "videoAllowFiles" ) );
+				conf.put( "fieldName", this.jsonConfig.getString( "videoFieldName" ) );
+				savePath = this.jsonConfig.getString( "videoPathFormat" );
+				break;
+				
+			case ActionMap.UPLOAD_SCRAWL:
+				conf.put( "filename", ConfigManager.SCRAWL_FILE_NAME );
+				conf.put( "maxSize", this.jsonConfig.getLong( "scrawlMaxSize" ) );
+				conf.put( "fieldName", this.jsonConfig.getString( "scrawlFieldName" ) );
+				conf.put( "isBase64", "true" );
+				savePath = this.jsonConfig.getString( "scrawlPathFormat" );
+				break;
+				
+			case ActionMap.CATCH_IMAGE:
+				conf.put( "filename", ConfigManager.REMOTE_FILE_NAME );
+				conf.put( "filter", this.getArray( "catcherLocalDomain" ) );
+				conf.put( "maxSize", this.jsonConfig.getLong( "catcherMaxSize" ) );
+				conf.put( "allowFiles", this.getArray( "catcherAllowFiles" ) );
+				conf.put( "fieldName", this.jsonConfig.getString( "catcherFieldName" ) + "[]" );
+				savePath = this.jsonConfig.getString( "catcherPathFormat" );
+				break;
+				
+			case ActionMap.LIST_IMAGE:
+				conf.put( "allowFiles", this.getArray( "imageManagerAllowFiles" ) );
+				conf.put( "dir", this.jsonConfig.getString( "imageManagerListPath" ) );
+				conf.put( "count", this.jsonConfig.getInt( "imageManagerListSize" ) );
+				break;
+				
+			case ActionMap.LIST_FILE:
+				conf.put( "allowFiles", this.getArray( "fileManagerAllowFiles" ) );
+				conf.put( "dir", this.jsonConfig.getString( "fileManagerListPath" ) );
+				conf.put( "count", this.jsonConfig.getInt( "fileManagerListSize" ) );
+				break;
+				
+		}
+		
+		conf.put( "savePath", savePath );
+		conf.put( "rootPath", this.rootPath );
+		
+		return conf;
+		
+	}
+	
+	private void initEnv () throws FileNotFoundException, IOException {
+		
+		File file = new File( this.originalPath );
+		
+		if ( !file.isAbsolute() ) {
+			file = new File( file.getAbsolutePath() );
+		}
+		
+		this.parentPath = file.getParent();
+		
+		String configContent = this.readFile( this.getConfigPath() );
+		
+		try{
+			JSONObject jsonConfig = new JSONObject( configContent );
+			this.jsonConfig = jsonConfig;
+		} catch ( Exception e ) {
+			this.jsonConfig = null;
+		}
+		
+	}
+	
+	private String getConfigPath () {
+		return this.parentPath + File.separator + ConfigManager.configFileName;
+	}
+
+	private String[] getArray ( String key ) {
+		
+		JSONArray jsonArray = this.jsonConfig.getJSONArray( key );
+		String[] result = new String[ jsonArray.length() ];
+		
+		for ( int i = 0, len = jsonArray.length(); i < len; i++ ) {
+			result[i] = jsonArray.getString( i );
+		}
+		
+		return result;
+		
+	}
+	
+	private String readFile ( String path ) throws IOException {
+		
+		StringBuilder builder = new StringBuilder();
+		
+		try {
+			
+			InputStreamReader reader = new InputStreamReader( new FileInputStream( path ), "UTF-8" );
+			BufferedReader bfReader = new BufferedReader( reader );
+			
+			String tmpContent = null;
+			
+			while ( ( tmpContent = bfReader.readLine() ) != null ) {
+				builder.append( tmpContent );
+			}
+			
+			bfReader.close();
+			
+		} catch ( UnsupportedEncodingException e ) {
+			// 忽略
+		}
+		return this.filter( builder.toString() );
+	}
+	
+	// 过滤输入字符串, 剔除多行注释以及替换掉反斜杠
+	private String filter ( String input ) {
+		
+		return input.replaceAll( "/\\*[\\s\\S]*?\\*/", "" );
+		
+	}
+	
+	public void updateConfig () {
+		
+		if(!UPCONFIG){
+			String modelPath = this.parentPath + File.separator + "config-model.json";
+			StringBuilder builder = new StringBuilder();
+			
+			try {
+				InputStreamReader reader = new InputStreamReader( new FileInputStream( modelPath ), "UTF-8" );
+				BufferedReader bfReader = new BufferedReader( reader );
+				
+				String tmpContent = null;
+				while ( ( tmpContent = bfReader.readLine() ) != null ) {
+					builder.append( tmpContent );
+				}
+				bfReader.close();
+				reader.close();
+				
+				String path = this.getConfigPath();
+				System.out.println("updatePath:"+path);
+				String newContent = builder.toString();
+				if("local".equals(DiaowenProperty.DWSTORAGETYPE)){
+//					newContent = newContent.replaceAll( "http://file.diaowen.net", DiaowenProperty.STORAGE_URL_PREFIX);
+					newContent = newContent.replaceAll( "http://file.diaowen.net/", InitAppliction.contextPath );
+//					newContent = newContent.replaceAll( "http://file.diaowen.net", "../" );
+				}else{
+					newContent = newContent.replaceAll( "http://file.diaowen.net/", DiaowenProperty.STORAGE_URL_PREFIX);
+				}
+				System.out.println(DiaowenProperty.STORAGE_URL_PREFIX);
+				// "imageUrlPrefix": "http://file.diaowen.net/", /* 图片访问路径前缀 */
+//				String newContent = newContent.replaceAll( "http://file.diaowen.net", DiaowenProperty.STORAGE_URL_PREFIX);
+				System.out.println(newContent);
+				OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(path), "UTF-8");
+				writer.write(newContent);
+				writer.close();
+				
+				
+//				System.out.println(ServletActionContext.getContext());
+				
+			} catch ( UnsupportedEncodingException e ) {
+				e.printStackTrace();
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+			UPCONFIG=true;
+		}
+		
+	}
+	
+}

+ 157 - 0
src/main/java/com/baidu/ueditor/CopyOfPathFormat.java

@@ -0,0 +1,157 @@
+package com.baidu.ueditor;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CopyOfPathFormat {
+	
+	private static final String TIME = "time";
+	private static final String FULL_YEAR = "yyyy";
+	private static final String YEAR = "yy";
+	private static final String MONTH = "mm";
+	private static final String DAY = "dd";
+	private static final String HOUR = "hh";
+	private static final String MINUTE = "ii";
+	private static final String SECOND = "ss";
+	private static final String RAND = "rand";
+	
+	private static Date currentDate = null;
+	
+	public static String parse ( String input ) {
+		
+		Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE  );
+		Matcher matcher = pattern.matcher(input);
+		
+		CopyOfPathFormat.currentDate = new Date();
+		
+		StringBuffer sb = new StringBuffer();
+		
+		while ( matcher.find() ) {
+			
+			matcher.appendReplacement(sb, CopyOfPathFormat.getString( matcher.group( 1 ) ) );
+			
+		}
+		
+		matcher.appendTail(sb);
+		
+		return sb.toString();
+	}
+	
+	/**
+	 * 格式化路径, 把windows路径替换成标准路径
+	 * @param input 待格式化的路径
+	 * @return 格式化后的路径
+	 */
+	public static String format ( String input ) {
+		
+		return input.replace( "\\", "/" );
+		
+	}
+
+	public static String parse ( String input, String filename ) {
+	
+		Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE  );
+		Matcher matcher = pattern.matcher(input);
+		String matchStr = null;
+		
+		CopyOfPathFormat.currentDate = new Date();
+		
+		StringBuffer sb = new StringBuffer();
+		
+		while ( matcher.find() ) {
+			
+			matchStr = matcher.group( 1 );
+			if ( matchStr.indexOf( "filename" ) != -1 ) {
+				filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" );
+				matcher.appendReplacement(sb, filename );
+			} else {
+				matcher.appendReplacement(sb, CopyOfPathFormat.getString( matchStr ) );
+			}
+			
+		}
+		
+		matcher.appendTail(sb);
+		
+		return sb.toString();
+	}
+		
+	private static String getString ( String pattern ) {
+		
+		pattern = pattern.toLowerCase();
+		
+		// time 处理
+		if ( pattern.indexOf( CopyOfPathFormat.TIME ) != -1 ) {
+			return CopyOfPathFormat.getTimestamp();
+		} else if ( pattern.indexOf( CopyOfPathFormat.FULL_YEAR ) != -1 ) {
+			return CopyOfPathFormat.getFullYear();
+		} else if ( pattern.indexOf( CopyOfPathFormat.YEAR ) != -1 ) {
+			return CopyOfPathFormat.getYear();
+		} else if ( pattern.indexOf( CopyOfPathFormat.MONTH ) != -1 ) {
+			return CopyOfPathFormat.getMonth();
+		} else if ( pattern.indexOf( CopyOfPathFormat.DAY ) != -1 ) {
+			return CopyOfPathFormat.getDay();
+		} else if ( pattern.indexOf( CopyOfPathFormat.HOUR ) != -1 ) {
+			return CopyOfPathFormat.getHour();
+		} else if ( pattern.indexOf( CopyOfPathFormat.MINUTE ) != -1 ) {
+			return CopyOfPathFormat.getMinute();
+		} else if ( pattern.indexOf( CopyOfPathFormat.SECOND ) != -1 ) {
+			return CopyOfPathFormat.getSecond();
+		} else if ( pattern.indexOf( CopyOfPathFormat.RAND ) != -1 ) {
+			return CopyOfPathFormat.getRandom( pattern );
+		} 
+		
+		return pattern;
+		
+	}
+
+	private static String getTimestamp () {
+		return System.currentTimeMillis() + "";
+	}
+	
+	private static String getFullYear () {
+		return new SimpleDateFormat( "yyyy" ).format( CopyOfPathFormat.currentDate );
+	}
+	
+	private static String getYear () {
+		return new SimpleDateFormat( "yy" ).format( CopyOfPathFormat.currentDate );
+	}
+	
+	private static String getMonth () {
+		return new SimpleDateFormat( "MM" ).format( CopyOfPathFormat.currentDate );
+	}
+	
+	private static String getDay () {
+		return new SimpleDateFormat( "dd" ).format( CopyOfPathFormat.currentDate );
+	}
+	
+	private static String getHour () {
+		return new SimpleDateFormat( "HH" ).format( CopyOfPathFormat.currentDate );
+	}
+	
+	private static String getMinute () {
+		return new SimpleDateFormat( "mm" ).format( CopyOfPathFormat.currentDate );
+	}
+	
+	private static String getSecond () {
+		return new SimpleDateFormat( "ss" ).format( CopyOfPathFormat.currentDate );
+	}
+	
+	private static String getRandom ( String pattern ) {
+		
+		int length = 0;
+		pattern = pattern.split( ":" )[ 1 ].trim();
+		
+		length = Integer.parseInt( pattern );
+		
+		return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length );
+		
+	}
+
+	public static void main(String[] args) {
+		// TODO Auto-generated method stub
+
+	}
+
+}

+ 24 - 0
src/main/java/com/baidu/ueditor/Encoder.java

@@ -0,0 +1,24 @@
+package com.baidu.ueditor;
+
+public class Encoder {
+
+	public static String toUnicode ( String input ) {
+		
+		StringBuilder builder = new StringBuilder();
+		char[] chars = input.toCharArray();
+		
+		for ( char ch : chars ) {
+			
+			if ( ch < 256 ) {
+				builder.append( ch );
+			} else {
+				builder.append( "\\u" +  Integer.toHexString( ch& 0xffff ) );
+			}
+			
+		}
+		
+		return builder.toString();
+		
+	}
+	
+}

+ 179 - 0
src/main/java/com/baidu/ueditor/PathFormat.java

@@ -0,0 +1,179 @@
+package com.baidu.ueditor;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.shiro.SecurityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.key.common.base.service.AccountManager;
+import com.key.common.plugs.security.MyDefaultWebSecurityManager;
+
+@Component
+public class PathFormat {
+	@Autowired
+	private AccountManager accountManager;
+	
+	private static final String TIME = "time";
+	private static final String FULL_YEAR = "yyyy";
+	private static final String YEAR = "yy";
+	private static final String MONTH = "mm";
+	private static final String DAY = "dd";
+	private static final String HOUR = "hh";
+	private static final String MINUTE = "ii";
+	private static final String SECOND = "ss";
+	private static final String RAND = "rand";
+	private static final String USERID = "userid";
+	
+	private static Date currentDate = null;
+	
+	public static String parse ( String input ) {
+		
+		Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE  );
+		Matcher matcher = pattern.matcher(input);
+		
+		PathFormat.currentDate = new Date();
+		
+		StringBuffer sb = new StringBuffer();
+		
+		while ( matcher.find() ) {
+			
+			matcher.appendReplacement(sb, PathFormat.getString( matcher.group( 1 ) ) );
+			
+		}
+		
+		matcher.appendTail(sb);
+		
+		return sb.toString();
+	}
+	
+	/**
+	 * 格式化路径, 把windows路径替换成标准路径
+	 * @param input 待格式化的路径
+	 * @return 格式化后的路径
+	 */
+	public static String format ( String input ) {
+		
+		return input.replace( "\\", "/" );
+		
+	}
+
+	public static String parse ( String input, String filename ) {
+	
+		Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE  );
+		Matcher matcher = pattern.matcher(input);
+		String matchStr = null;
+		
+		PathFormat.currentDate = new Date();
+		
+		StringBuffer sb = new StringBuffer();
+		
+		while ( matcher.find() ) {
+			
+			matchStr = matcher.group( 1 );
+			if ( matchStr.indexOf( "filename" ) != -1 ) {
+				filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" );
+				matcher.appendReplacement(sb, filename );
+			} else {
+				matcher.appendReplacement(sb, PathFormat.getString( matchStr ) );
+			}
+			
+		}
+		
+		matcher.appendTail(sb);
+		
+		return sb.toString();
+	}
+		
+	private static String getString ( String pattern ) {
+		
+		pattern = pattern.toLowerCase();
+		
+		// time 处理
+		if ( pattern.indexOf( PathFormat.TIME ) != -1 ) {
+			return PathFormat.getTimestamp();
+		} else if ( pattern.indexOf( PathFormat.FULL_YEAR ) != -1 ) {
+			return PathFormat.getFullYear();
+		} else if ( pattern.indexOf( PathFormat.YEAR ) != -1 ) {
+			return PathFormat.getYear();
+		} else if ( pattern.indexOf( PathFormat.MONTH ) != -1 ) {
+			return PathFormat.getMonth();
+		} else if ( pattern.indexOf( PathFormat.DAY ) != -1 ) {
+			return PathFormat.getDay();
+		} else if ( pattern.indexOf( PathFormat.HOUR ) != -1 ) {
+			return PathFormat.getHour();
+		} else if ( pattern.indexOf( PathFormat.MINUTE ) != -1 ) {
+			return PathFormat.getMinute();
+		} else if ( pattern.indexOf( PathFormat.SECOND ) != -1 ) {
+			return PathFormat.getSecond();
+		} else if ( pattern.indexOf( PathFormat.RAND ) != -1 ) {
+			return PathFormat.getRandom( pattern );
+		} else if (pattern.indexOf( PathFormat.USERID ) != -1){
+			return PathFormat.getUserId();
+		}
+		
+		return pattern;
+		
+	}
+	
+	public static String getUserId() {
+		MyDefaultWebSecurityManager security=(MyDefaultWebSecurityManager)SecurityUtils.getSecurityManager();
+		String userId=security.getUserId();
+		if(userId==null){
+			userId="otheruser";
+		}
+		return userId;
+	}
+	
+	private static String getTimestamp () {
+		return System.currentTimeMillis() + "";
+	}
+	
+	private static String getFullYear () {
+		return new SimpleDateFormat( "yyyy" ).format( PathFormat.currentDate );
+	}
+	
+	private static String getYear () {
+		return new SimpleDateFormat( "yy" ).format( PathFormat.currentDate );
+	}
+	
+	private static String getMonth () {
+		return new SimpleDateFormat( "MM" ).format( PathFormat.currentDate );
+	}
+	
+	private static String getDay () {
+		return new SimpleDateFormat( "dd" ).format( PathFormat.currentDate );
+	}
+	
+	private static String getHour () {
+		return new SimpleDateFormat( "HH" ).format( PathFormat.currentDate );
+	}
+	
+	private static String getMinute () {
+		return new SimpleDateFormat( "mm" ).format( PathFormat.currentDate );
+	}
+	
+	private static String getSecond () {
+		return new SimpleDateFormat( "ss" ).format( PathFormat.currentDate );
+	}
+	
+	private static String getRandom ( String pattern ) {
+		
+		int length = 0;
+		pattern = pattern.split( ":" )[ 1 ].trim();
+		
+		length = Integer.parseInt( pattern );
+		
+		return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length );
+		
+	}
+
+	public static void main(String[] args) {
+		// TODO Auto-generated method stub
+
+	}
+
+}

+ 42 - 0
src/main/java/com/baidu/ueditor/define/ActionMap.java

@@ -0,0 +1,42 @@
+package com.baidu.ueditor.define;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * 定义请求action类型
+ * @author hancong03@baidu.com
+ *
+ */
+@SuppressWarnings("serial")
+public final class ActionMap {
+
+	public static final Map<String, Integer> mapping;
+	// 获取配置请求
+	public static final int CONFIG = 0;
+	public static final int UPLOAD_IMAGE = 1;
+	public static final int UPLOAD_SCRAWL = 2;
+	public static final int UPLOAD_VIDEO = 3;
+	public static final int UPLOAD_FILE = 4;
+	public static final int CATCH_IMAGE = 5;
+	public static final int LIST_FILE = 6;
+	public static final int LIST_IMAGE = 7;
+	
+	static {
+		mapping = new HashMap<String, Integer>(){{
+			put( "config", ActionMap.CONFIG );
+			put( "uploadimage", ActionMap.UPLOAD_IMAGE );
+			put( "uploadscrawl", ActionMap.UPLOAD_SCRAWL );
+			put( "uploadvideo", ActionMap.UPLOAD_VIDEO );
+			put( "uploadfile", ActionMap.UPLOAD_FILE );
+			put( "catchimage", ActionMap.CATCH_IMAGE );
+			put( "listfile", ActionMap.LIST_FILE );
+			put( "listimage", ActionMap.LIST_IMAGE );
+		}};
+	}
+	
+	public static int getType ( String key ) {
+		return ActionMap.mapping.get( key );
+	}
+	
+}

+ 5 - 0
src/main/java/com/baidu/ueditor/define/ActionState.java

@@ -0,0 +1,5 @@
+package com.baidu.ueditor.define;
+
+public enum ActionState {
+	UNKNOW_ERROR
+}

+ 77 - 0
src/main/java/com/baidu/ueditor/define/AppInfo.java

@@ -0,0 +1,77 @@
+package com.baidu.ueditor.define;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public final class AppInfo {
+	
+	public static final int SUCCESS = 0;
+	public static final int MAX_SIZE = 1;
+	public static final int PERMISSION_DENIED = 2;
+	public static final int FAILED_CREATE_FILE = 3;
+	public static final int IO_ERROR = 4;
+	public static final int NOT_MULTIPART_CONTENT = 5;
+	public static final int PARSE_REQUEST_ERROR = 6;
+	public static final int NOTFOUND_UPLOAD_DATA = 7;
+	public static final int NOT_ALLOW_FILE_TYPE = 8;
+	
+	public static final int INVALID_ACTION = 101;
+	public static final int CONFIG_ERROR = 102;
+	
+	public static final int PREVENT_HOST = 201;
+	public static final int CONNECTION_ERROR = 202;
+	public static final int REMOTE_FAIL = 203;
+	
+	public static final int NOT_DIRECTORY = 301;
+	public static final int NOT_EXIST = 302;
+	
+	public static final int ILLEGAL = 401;
+
+	public static Map<Integer, String> info = new HashMap<Integer, String>(){{
+		
+		put( AppInfo.SUCCESS, "SUCCESS" );
+		
+		// 无效的Action
+		put( AppInfo.INVALID_ACTION, "\u65E0\u6548\u7684Action" );
+		// 配置文件初始化失败
+		put( AppInfo.CONFIG_ERROR, "\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u5931\u8D25" );
+		// 抓取远程图片失败
+		put( AppInfo.REMOTE_FAIL, "\u6293\u53D6\u8FDC\u7A0B\u56FE\u7247\u5931\u8D25" );
+		
+		// 被阻止的远程主机
+		put( AppInfo.PREVENT_HOST, "\u88AB\u963B\u6B62\u7684\u8FDC\u7A0B\u4E3B\u673A" );
+		// 远程连接出错
+		put( AppInfo.CONNECTION_ERROR, "\u8FDC\u7A0B\u8FDE\u63A5\u51FA\u9519" );
+		
+		// "文件大小超出限制"
+		put( AppInfo.MAX_SIZE, "\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236" );
+		// 权限不足, 多指写权限
+		put( AppInfo.PERMISSION_DENIED, "\u6743\u9650\u4E0D\u8DB3" );
+		// 创建文件失败
+		put( AppInfo.FAILED_CREATE_FILE, "\u521B\u5EFA\u6587\u4EF6\u5931\u8D25" );
+		// IO错误
+		put( AppInfo.IO_ERROR, "IO\u9519\u8BEF" );
+		// 上传表单不是multipart/form-data类型
+		put( AppInfo.NOT_MULTIPART_CONTENT, "\u4E0A\u4F20\u8868\u5355\u4E0D\u662Fmultipart/form-data\u7C7B\u578B" );
+		// 解析上传表单错误
+		put( AppInfo.PARSE_REQUEST_ERROR, "\u89E3\u6790\u4E0A\u4F20\u8868\u5355\u9519\u8BEF" );
+		// 未找到上传数据
+		put( AppInfo.NOTFOUND_UPLOAD_DATA, "\u672A\u627E\u5230\u4E0A\u4F20\u6570\u636E" );
+		// 不允许的文件类型
+		put( AppInfo.NOT_ALLOW_FILE_TYPE, "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B" );
+		
+		// 指定路径不是目录
+		put( AppInfo.NOT_DIRECTORY, "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55" );
+		// 指定路径并不存在
+		put( AppInfo.NOT_EXIST, "\u6307\u5B9A\u8DEF\u5F84\u5E76\u4E0D\u5B58\u5728" );
+		
+		// callback参数名不合法
+		put( AppInfo.ILLEGAL, "Callback\u53C2\u6570\u540D\u4E0D\u5408\u6CD5" );
+		
+	}};
+	
+	public static String getStateInfo ( int key ) {
+		return AppInfo.info.get( key );
+	}
+	
+}

+ 90 - 0
src/main/java/com/baidu/ueditor/define/BaseState.java

@@ -0,0 +1,90 @@
+package com.baidu.ueditor.define;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import com.baidu.ueditor.Encoder;
+
+public class BaseState implements State {
+
+	private boolean state = false;
+	private String info = null;
+	
+	private Map<String, String> infoMap = new HashMap<String, String>();
+	
+	public BaseState () {
+		this.state = true;
+	}
+	
+	public BaseState ( boolean state ) {
+		this.setState( state );
+	}
+	
+	public BaseState ( boolean state, String info ) {
+		this.setState( state );
+		this.info = info;
+	}
+	
+	public BaseState ( boolean state, int infoCode ) {
+		this.setState( state );
+		this.info = AppInfo.getStateInfo( infoCode );
+	}
+	
+	public boolean isSuccess () {
+		return this.state;
+	}
+	
+	public void setState ( boolean state ) {
+		this.state = state;
+	}
+	
+	public void setInfo ( String info ) {
+		this.info = info;
+	}
+	
+	public void setInfo ( int infoCode ) {
+		this.info = AppInfo.getStateInfo( infoCode );
+	}
+	
+	@Override
+	public String toJSONString() {
+		return this.toString();
+	}
+	
+	public String toString () {
+		
+		String key = null;
+		String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info;
+		
+		StringBuilder builder = new StringBuilder();
+		
+		builder.append( "{\"state\": \"" + stateVal + "\"" );
+		
+		Iterator<String> iterator = this.infoMap.keySet().iterator();
+		
+		while ( iterator.hasNext() ) {
+			
+			key = iterator.next();
+			
+			builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" );
+			
+		}
+		
+		builder.append( "}" );
+
+		return Encoder.toUnicode( builder.toString() );
+
+	}
+
+	@Override
+	public void putInfo(String name, String val) {
+		this.infoMap.put(name, val);
+	}
+
+	@Override
+	public void putInfo(String name, long val) {
+		this.putInfo(name, val+"");
+	}
+
+}

+ 31 - 0
src/main/java/com/baidu/ueditor/define/FileType.java

@@ -0,0 +1,31 @@
+package com.baidu.ueditor.define;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FileType {
+
+	public static final String JPG = "JPG";
+	
+	private static final Map<String, String> types = new HashMap<String, String>(){{
+		
+		put( FileType.JPG, ".jpg" );
+		
+	}};
+	
+	public static String getSuffix ( String key ) {
+		return FileType.types.get( key );
+	}
+	
+	/**
+	 * 根据给定的文件名,获取其后缀信息
+	 * @param filename
+	 * @return
+	 */
+	public static String getSuffixByFilename ( String filename ) {
+		
+		return filename.substring( filename.lastIndexOf( "." ) ).toLowerCase();
+		
+	}
+	
+}

+ 20 - 0
src/main/java/com/baidu/ueditor/define/MIMEType.java

@@ -0,0 +1,20 @@
+package com.baidu.ueditor.define;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MIMEType {
+
+	public static final Map<String, String> types = new HashMap<String, String>(){{
+		put( "image/gif", ".gif" );
+		put( "image/jpeg", ".jpg" );
+		put( "image/jpg", ".jpg" );
+		put( "image/png", ".png" );
+		put( "image/bmp", ".bmp" );
+	}};
+	
+	public static String getSuffix ( String mime ) {
+		return MIMEType.types.get( mime );
+	}
+	
+}

+ 112 - 0
src/main/java/com/baidu/ueditor/define/MultiState.java

@@ -0,0 +1,112 @@
+package com.baidu.ueditor.define;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.baidu.ueditor.Encoder;
+
+/**
+ * 多状态集合状态
+ * 其包含了多个状态的集合, 其本身自己也是一个状态
+ * @author hancong03@baidu.com
+ *
+ */
+public class MultiState implements State {
+
+	private boolean state = false;
+	private String info = null;
+	private Map<String, Long> intMap = new HashMap<String, Long>();
+	private Map<String, String> infoMap = new HashMap<String, String>();
+	private List<String> stateList = new ArrayList<String>();
+	
+	public MultiState ( boolean state ) {
+		this.state = state;
+	}
+	
+	public MultiState ( boolean state, String info ) {
+		this.state = state;
+		this.info = info;
+	}
+	
+	public MultiState ( boolean state, int infoKey ) {
+		this.state = state;
+		this.info = AppInfo.getStateInfo( infoKey );
+	}
+	
+	@Override
+	public boolean isSuccess() {
+		return this.state;
+	}
+	
+	public void addState ( State state ) {
+		stateList.add( state.toJSONString() );
+	}
+
+	/**
+	 * 该方法调用无效果
+	 */
+	@Override
+	public void putInfo(String name, String val) {
+		this.infoMap.put(name, val);
+	}
+
+	@Override
+	public String toJSONString() {
+		
+		String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info;
+		
+		StringBuilder builder = new StringBuilder();
+		
+		builder.append( "{\"state\": \"" + stateVal + "\"" );
+		
+		// 数字转换
+		Iterator<String> iterator = this.intMap.keySet().iterator();
+		
+		while ( iterator.hasNext() ) {
+			
+			stateVal = iterator.next();
+			
+			builder.append( ",\""+ stateVal +"\": " + this.intMap.get( stateVal ) );
+			
+		}
+		
+		iterator = this.infoMap.keySet().iterator();
+		
+		while ( iterator.hasNext() ) {
+			
+			stateVal = iterator.next();
+			
+			builder.append( ",\""+ stateVal +"\": \"" + this.infoMap.get( stateVal ) + "\"" );
+			
+		}
+		
+		builder.append( ", list: [" );
+		
+		
+		iterator = this.stateList.iterator();
+		
+		while ( iterator.hasNext() ) {
+			
+			builder.append( iterator.next() + "," );
+			
+		}
+		
+		if ( this.stateList.size() > 0 ) {
+			builder.deleteCharAt( builder.length() - 1 );
+		}
+		
+		builder.append( " ]}" );
+
+		return Encoder.toUnicode( builder.toString() );
+
+	}
+
+	@Override
+	public void putInfo(String name, long val) {
+		this.intMap.put( name, val );
+	}
+
+}

+ 18 - 0
src/main/java/com/baidu/ueditor/define/State.java

@@ -0,0 +1,18 @@
+package com.baidu.ueditor.define;
+
+/**
+ * 处理状态接口
+ * @author hancong03@baidu.com
+ *
+ */
+public interface State {
+	
+	public boolean isSuccess ();
+	
+	public void putInfo( String name, String val );
+	
+	public void putInfo ( String name, long val );
+	
+	public String toJSONString ();
+
+}

+ 112 - 0
src/main/java/com/baidu/ueditor/hunter/CopyOfFileManager.java

@@ -0,0 +1,112 @@
+package com.baidu.ueditor.hunter;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+
+import com.baidu.ueditor.PathFormat;
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.MultiState;
+import com.baidu.ueditor.define.State;
+
+public class CopyOfFileManager {/*
+
+	private String dir = null;
+	private String rootPath = null;
+	private String[] allowFiles = null;
+	private int count = 0;
+	
+	public CopyOfFileManager ( Map<String, Object> conf ) {
+
+		this.rootPath = (String)conf.get( "rootPath" );
+		this.dir = this.rootPath + (String)conf.get( "dir" );
+		this.allowFiles = this.getAllowFiles( conf.get("allowFiles") );
+		this.count = (Integer)conf.get( "count" );
+		
+	}
+	
+	public State listFile ( int index ) {
+		
+		File dir = new File( this.dir );
+		State state = null;
+
+		if ( !dir.exists() ) {
+			return new BaseState( false, AppInfo.NOT_EXIST );
+		}
+		
+		if ( !dir.isDirectory() ) {
+			return new BaseState( false, AppInfo.NOT_DIRECTORY );
+		}
+		
+		Collection<File> list = FileUtils.listFiles( dir, this.allowFiles, true );
+		
+		if ( index < 0 || index > list.size() ) {
+			state = new MultiState( true );
+		} else {
+			Object[] fileList = Arrays.copyOfRange( list.toArray(), index, index + this.count );
+			state = this.getState( fileList );
+		}
+		
+		state.putInfo( "start", index );
+		state.putInfo( "total", list.size() );
+		
+		return state;
+		
+	}
+	
+	private State getState ( Object[] files ) {
+		
+		MultiState state = new MultiState( true );
+		BaseState fileState = null;
+		
+		File file = null;
+		
+		for ( Object obj : files ) {
+			if ( obj == null ) {
+				break;
+			}
+			file = (File)obj;
+			fileState = new BaseState( true );
+			fileState.putInfo( "url", PathFormat.format( this.getPath( file ) ) );
+			state.addState( fileState );
+		}
+		
+		return state;
+		
+	}
+	
+	private String getPath ( File file ) {
+//		String path = file.getAbsolutePath();
+		//后来自己回的
+		String path=PathFormat.format(file.getAbsolutePath());
+		return path.replace( this.rootPath, "/" );
+		
+	}
+	
+	private String[] getAllowFiles ( Object fileExt ) {
+		
+		String[] exts = null;
+		String ext = null;
+		
+		if ( fileExt == null ) {
+			return new String[ 0 ];
+		}
+		
+		exts = (String[])fileExt;
+		
+		for ( int i = 0, len = exts.length; i < len; i++ ) {
+			
+			ext = exts[ i ];
+			exts[ i ] = ext.replace( ".", "" );
+			
+		}
+		
+		return exts;
+		
+	}
+	
+*/}

+ 215 - 0
src/main/java/com/baidu/ueditor/hunter/FileManager.java

@@ -0,0 +1,215 @@
+package com.baidu.ueditor.hunter;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+
+import com.aliyun.oss.model.OSSObjectSummary;
+import com.baidu.ueditor.PathFormat;
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.MultiState;
+import com.baidu.ueditor.define.State;
+import com.baidubce.services.bos.model.BosObjectSummary;
+import com.key.common.plugs.aliyun.AliyunOSS;
+import com.key.common.plugs.baiduyun.BaiduBOS;
+import com.key.common.utils.DiaowenProperty;
+
+public class FileManager {
+
+	private String dir = null;
+	private String rootPath = null;
+	private String[] allowFiles = null;
+	private int count = 0;
+	
+	public FileManager ( Map<String, Object> conf ) {
+
+		this.rootPath = (String)conf.get( "rootPath" );
+//		this.dir = this.rootPath + (String)conf.get( "dir" );
+		this.dir = (String)conf.get( "dir" );
+		this.allowFiles = this.getAllowFiles( conf.get("allowFiles") );
+		this.count = (Integer)conf.get( "count" );
+		
+	}
+	
+	public State listFile ( int index ) {
+		
+		if("local".equals(DiaowenProperty.DWSTORAGETYPE)) {
+			File dir = new File( this.rootPath + this.dir );
+			
+			System.out.println("dir:"+this.rootPath + this.dir);
+			State state = null;
+
+			if ( !dir.exists() ) {
+				return new BaseState( false, AppInfo.NOT_EXIST );
+			}
+			
+			if ( !dir.isDirectory() ) {
+				return new BaseState( false, AppInfo.NOT_DIRECTORY );
+			}
+			
+			Collection<File> list = FileUtils.listFiles( dir, this.allowFiles, true );
+			
+			for (File file : list) {
+				System.out.println(file.getName());
+			}
+			if ( index < 0 || index > list.size() ) {
+				state = new MultiState( true );
+			} else {
+				Object[] fileList = Arrays.copyOfRange( list.toArray(), index, index + this.count );
+				state = this.getState( fileList );
+			}
+			
+			state.putInfo( "start", index );
+			state.putInfo( "total", list.size() );
+			
+			return state;
+		}else{
+			
+			return listFileByYun(index);
+			
+		}
+		
+	}
+	
+	
+	private State getState ( Object[] files ) {
+		
+		MultiState state = new MultiState( true );
+		BaseState fileState = null;
+		
+		File file = null;
+		
+		for ( Object obj : files ) {
+			if ( obj == null ) {
+				break;
+			}
+			file = (File)obj;
+			fileState = new BaseState( true );
+			fileState.putInfo( "url", PathFormat.format( this.getPath( file ) ) );
+			state.addState( fileState );
+		}
+		
+		return state;
+		
+	}
+	
+
+/*	private String getPath ( File file ) {
+		
+		String path = file.getAbsolutePath();
+		
+		return path.replace( this.rootPath, "/" );
+		
+	}
+*/
+
+	private String getPath ( File file ) {
+//		String path = file.getAbsolutePath();
+		//后来自己回的
+		String path=PathFormat.format(file.getAbsolutePath());
+		return path.replace( this.rootPath, "/" );
+		
+	}
+	
+	private String[] getAllowFiles ( Object fileExt ) {
+		
+		String[] exts = null;
+		String ext = null;
+		
+		if ( fileExt == null ) {
+			return new String[ 0 ];
+		}
+		
+		exts = (String[])fileExt;
+		
+		for ( int i = 0, len = exts.length; i < len; i++ ) {
+			
+			ext = exts[ i ];
+			exts[ i ] = ext.replace( ".", "" );
+			
+		}
+		
+		return exts;
+		
+	}
+	
+	/*
+	 * yun实现的操作
+	 */
+	public State listFileByYun ( int index ) {
+		dir=dir.substring(1);
+		
+		//得到当前用户
+		String userId=PathFormat.getUserId();
+		dir=dir+userId+"/";
+		State state = null;
+		try{
+			Collection list = null;
+			if("aliyunOSS".equals(DiaowenProperty.DWSTORAGETYPE)){
+				// 阿里云支持 
+				list = AliyunOSS.getObjectList(DiaowenProperty.UPLOADFILE_BACKET, dir,index+count,count);
+			}else if("baiduBOS".equals(DiaowenProperty.DWSTORAGETYPE)){
+				list = BaiduBOS.getObjectList(DiaowenProperty.UPLOADFILE_BACKET, dir,index+count,count);
+				
+			}
+
+			if ( index < 0 || index > list.size() ) {
+				state = new MultiState( true );
+			} else {
+				Object[] fileList = Arrays.copyOfRange( list.toArray(), index, index + this.count );
+				state = this.getStateByYun( fileList );
+			}
+			
+			state.putInfo( "start", index );
+			state.putInfo( "total", list.size() );
+			
+		}catch(Exception e){
+			state = new BaseState( false, AppInfo.NOT_EXIST );
+			e.printStackTrace();
+		}
+		
+		return state;
+		
+	}
+	
+	private State getStateByYun ( Object[] files ) {
+		
+		MultiState state = new MultiState( true );
+		BaseState fileState = null;
+		
+		
+		for ( Object obj : files ) {
+			if ( obj == null ) {
+				break;
+			}
+			
+			if(obj instanceof OSSObjectSummary ){
+				OSSObjectSummary file = (OSSObjectSummary)obj;
+
+				fileState = new BaseState( true );
+//				fileState.putInfo( "url", "http://file.diaowen.net/"+PathFormat.format( file.getKey() ) );
+				fileState.putInfo( "url", PathFormat.format( file.getKey() ) );
+				state.addState( fileState );
+				
+			}else{
+				//obj instanceof BosObjectSummary 
+				BosObjectSummary file = (BosObjectSummary)obj;
+				
+				fileState = new BaseState( true );
+//				fileState.putInfo( "url", "http://file.diaowen.net/"+PathFormat.format( file.getKey() ) );
+				fileState.putInfo( "url", PathFormat.format( file.getKey() ) );
+				state.addState( fileState );
+			}
+			
+		}
+		
+		return state;
+		
+	}
+	
+	
+}

+ 135 - 0
src/main/java/com/baidu/ueditor/hunter/ImageHunter.java

@@ -0,0 +1,135 @@
+package com.baidu.ueditor.hunter;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import com.baidu.ueditor.PathFormat;
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.MIMEType;
+import com.baidu.ueditor.define.MultiState;
+import com.baidu.ueditor.define.State;
+import com.baidu.ueditor.upload.StorageManager;
+
+/**
+ * 图片抓取器
+ * @author hancong03@baidu.com
+ *
+ */
+public class ImageHunter {
+
+	private String filename = null;
+	private String savePath = null;
+	private String rootPath = null;
+	private List<String> allowTypes = null;
+	private long maxSize = -1;
+	
+	private List<String> filters = null;
+	
+	public ImageHunter ( Map<String, Object> conf ) {
+		
+		this.filename = (String)conf.get( "filename" );
+		this.savePath = (String)conf.get( "savePath" );
+		this.rootPath = (String)conf.get( "rootPath" );
+		this.maxSize = (Long)conf.get( "maxSize" );
+		this.allowTypes = Arrays.asList( (String[])conf.get( "allowFiles" ) );
+		this.filters = Arrays.asList( (String[])conf.get( "filter" ) );
+		
+	}
+	
+	public State capture ( String[] list ) {
+		
+		MultiState state = new MultiState( true );
+		
+		for ( String source : list ) {
+			state.addState( captureRemoteData( source ) );
+		}
+		
+		return state;
+		
+	}
+
+	public State captureRemoteData ( String urlStr ) {
+		
+		HttpURLConnection connection = null;
+		URL url = null;
+		String suffix = null;
+		
+		try {
+			url = new URL( urlStr );
+
+			if ( !validHost( url.getHost() ) ) {
+				return new BaseState( false, AppInfo.PREVENT_HOST );
+			}
+			
+			connection = (HttpURLConnection) url.openConnection();
+		
+			connection.setInstanceFollowRedirects( true );
+			connection.setUseCaches( true );
+		
+			if ( !validContentState( connection.getResponseCode() ) ) {
+				return new BaseState( false, AppInfo.CONNECTION_ERROR );
+			}
+			
+			suffix = MIMEType.getSuffix( connection.getContentType() );
+			
+			if ( !validFileType( suffix ) ) {
+				return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE );
+			}
+			
+			if ( !validFileSize( connection.getContentLength() ) ) {
+				return new BaseState( false, AppInfo.MAX_SIZE );
+			}
+			
+			String savePath = this.getPath( this.savePath, this.filename, suffix );
+//			String physicalPath = this.rootPath + savePath;
+//			State state = StorageManager.saveFileByInputStream( connection.getInputStream(), physicalPath );
+			State state = StorageManager.saveFileByInputStream( connection.getInputStream(), this.rootPath, savePath);
+//			State state = StorageManager.saveFileByInputStreamToYun( connection.getInputStream(), savePath );
+			
+			if ( state.isSuccess() ) {
+				state.putInfo( "url", PathFormat.format( savePath ) );
+//				state.putInfo( "url", "http://file.diaowen.net"+PathFormat.format( savePath ) );
+				state.putInfo( "source", urlStr );
+			}
+			
+			return state;
+			
+		} catch ( Exception e ) {
+			return new BaseState( false, AppInfo.REMOTE_FAIL );
+		}
+		
+	}
+	
+	private String getPath ( String savePath, String filename, String suffix  ) {
+		
+		return PathFormat.parse( savePath + suffix, filename );
+		
+	}
+	
+	private boolean validHost ( String hostname ) {
+		
+		return !filters.contains( hostname );
+		
+	}
+	
+	private boolean validContentState ( int code ) {
+		
+		return HttpURLConnection.HTTP_OK == code;
+		
+	}
+	
+	private boolean validFileType ( String type ) {
+		
+		return this.allowTypes.contains( type );
+		
+	}
+	
+	private boolean validFileSize ( int size ) {
+		return size < this.maxSize;
+	}
+	
+}

+ 54 - 0
src/main/java/com/baidu/ueditor/upload/Base64Uploader.java

@@ -0,0 +1,54 @@
+package com.baidu.ueditor.upload;
+
+import com.baidu.ueditor.PathFormat;
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.FileType;
+import com.baidu.ueditor.define.State;
+
+import java.util.Map;
+
+import org.apache.commons.codec.binary.Base64;
+
+public final class Base64Uploader {
+
+	public static State save(String content, Map<String, Object> conf) {
+		
+		byte[] data = decode(content);
+
+		long maxSize = ((Long) conf.get("maxSize")).longValue();
+
+		if (!validSize(data, maxSize)) {
+			return new BaseState(false, AppInfo.MAX_SIZE);
+		}
+
+		String suffix = FileType.getSuffix("JPG");
+
+		String savePath = PathFormat.parse((String) conf.get("savePath"),
+				(String) conf.get("filename"));
+		
+		savePath = savePath + suffix;
+//		String physicalPath = (String) conf.get("rootPath") + savePath;
+//		State storageState = StorageManager.saveBinaryFile(data, savePath);
+		State storageState = StorageManager.saveBinaryFile(data, (String) conf.get("rootPath"), savePath); 
+//		State storageState = StorageManager.saveBinaryFileToYun(data, savePath);
+
+		if (storageState.isSuccess()) {
+			storageState.putInfo("url", PathFormat.format(savePath));
+//			storageState.putInfo("url", "http://file.diaowen.net"+PathFormat.format(savePath));
+			storageState.putInfo("type", suffix);
+			storageState.putInfo("original", "");
+		}
+
+		return storageState;
+	}
+
+	private static byte[] decode(String content) {
+		return Base64.decodeBase64(content);
+	}
+
+	private static boolean validSize(byte[] data, long length) {
+		return data.length <= length;
+	}
+	
+}

+ 110 - 0
src/main/java/com/baidu/ueditor/upload/BinaryUploader.java

@@ -0,0 +1,110 @@
+package com.baidu.ueditor.upload;
+
+import com.baidu.ueditor.PathFormat;
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.FileType;
+import com.baidu.ueditor.define.State;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileItemStream;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+public class BinaryUploader {
+
+	public static final State save(HttpServletRequest request,
+			Map<String, Object> conf) {
+		FileItemStream fileStream = null;
+		boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;
+
+		if (!ServletFileUpload.isMultipartContent(request)) {
+			return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
+		}
+
+		ServletFileUpload upload = new ServletFileUpload(
+				new DiskFileItemFactory());
+
+        if ( isAjaxUpload ) {
+            upload.setHeaderEncoding( "UTF-8" );
+        }
+
+		try {
+			FileItemIterator iterator = upload.getItemIterator(request);
+
+			while (iterator.hasNext()) {
+				fileStream = iterator.next();
+
+				if (!fileStream.isFormField())
+					break;
+				fileStream = null;
+			}
+
+			if (fileStream == null) {
+				return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
+			}
+
+			String savePath = (String) conf.get("savePath");
+			String originFileName = fileStream.getName();
+			String suffix = FileType.getSuffixByFilename(originFileName);
+
+			
+			originFileName = originFileName.substring(0,
+					originFileName.length() - suffix.length());
+			savePath = savePath + suffix;
+
+			long maxSize = ((Long) conf.get("maxSize")).longValue();
+
+			if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
+				return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
+			}
+			
+			
+			savePath = PathFormat.parse(savePath, originFileName);
+			/*
+			String physicalPath = (String) conf.get("rootPath") + savePath;
+
+			InputStream is = fileStream.openStream();
+			State storageState = StorageManager.saveFileByInputStream(is,
+					physicalPath, maxSize);
+			is.close();
+			*/
+			InputStream is = fileStream.openStream();
+			State storageState = StorageManager.saveFileByInputStream(is, (String) conf.get("rootPath"), savePath, maxSize);
+//			InputStream is = fileStream.openStream();
+//			State storageState = StorageManager.saveFileByInputStreamToYun(is, savePath);
+			if(storageState!=null){
+				storageState.putInfo( "title", originFileName);
+			}
+			is.close();
+			
+			if (storageState.isSuccess()) {
+				storageState.putInfo("url", PathFormat.format(savePath));
+//				storageState.putInfo("url", "http://file.diaowen.net"+PathFormat.format(savePath));
+				storageState.putInfo("type", suffix);
+				storageState.putInfo("original", originFileName + suffix);
+			}
+
+			return storageState;
+		} catch (FileUploadException e) {
+			return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
+		} catch (IOException e) {
+		}
+		return new BaseState(false, AppInfo.IO_ERROR);
+	}
+
+	private static boolean validType(String type, String[] allowTypes) {
+		List<String> list = Arrays.asList(allowTypes);
+
+		return list.contains(type);
+	}
+}

+ 52 - 0
src/main/java/com/baidu/ueditor/upload/CopyOfBase64Uploader.java

@@ -0,0 +1,52 @@
+package com.baidu.ueditor.upload;
+
+import com.baidu.ueditor.PathFormat;
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.FileType;
+import com.baidu.ueditor.define.State;
+
+import java.util.Map;
+
+import org.apache.commons.codec.binary.Base64;
+
+public final class CopyOfBase64Uploader {/*
+
+	public static State save(String content, Map<String, Object> conf) {
+		
+		byte[] data = decode(content);
+
+		long maxSize = ((Long) conf.get("maxSize")).longValue();
+
+		if (!validSize(data, maxSize)) {
+			return new BaseState(false, AppInfo.MAX_SIZE);
+		}
+
+		String suffix = FileType.getSuffix("JPG");
+
+		String savePath = PathFormat.parse((String) conf.get("savePath"),
+				(String) conf.get("filename"));
+		
+		savePath = savePath + suffix;
+		String physicalPath = (String) conf.get("rootPath") + savePath;
+
+		State storageState = StorageManager.saveBinaryFile(data, physicalPath);
+
+		if (storageState.isSuccess()) {
+			storageState.putInfo("url", PathFormat.format(savePath));
+			storageState.putInfo("type", suffix);
+			storageState.putInfo("original", "");
+		}
+
+		return storageState;
+	}
+
+	private static byte[] decode(String content) {
+		return Base64.decodeBase64(content);
+	}
+
+	private static boolean validSize(byte[] data, long length) {
+		return data.length <= length;
+	}
+	
+*/}

+ 98 - 0
src/main/java/com/baidu/ueditor/upload/CopyOfBinaryUploader.java

@@ -0,0 +1,98 @@
+package com.baidu.ueditor.upload;
+
+import com.baidu.ueditor.PathFormat;
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.FileType;
+import com.baidu.ueditor.define.State;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileItemStream;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+public class CopyOfBinaryUploader {
+/*
+	public static final State save(HttpServletRequest request,
+			Map<String, Object> conf) {
+		FileItemStream fileStream = null;
+		boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;
+
+		if (!ServletFileUpload.isMultipartContent(request)) {
+			return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
+		}
+
+		ServletFileUpload upload = new ServletFileUpload(
+				new DiskFileItemFactory());
+
+        if ( isAjaxUpload ) {
+            upload.setHeaderEncoding( "UTF-8" );
+        }
+
+		try {
+			FileItemIterator iterator = upload.getItemIterator(request);
+
+			while (iterator.hasNext()) {
+				fileStream = iterator.next();
+
+				if (!fileStream.isFormField())
+					break;
+				fileStream = null;
+			}
+
+			if (fileStream == null) {
+				return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
+			}
+
+			String savePath = (String) conf.get("savePath");
+			String originFileName = fileStream.getName();
+			String suffix = FileType.getSuffixByFilename(originFileName);
+
+			originFileName = originFileName.substring(0,
+					originFileName.length() - suffix.length());
+			savePath = savePath + suffix;
+
+			long maxSize = ((Long) conf.get("maxSize")).longValue();
+
+			if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
+				return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
+			}
+
+			savePath = PathFormat.parse(savePath, originFileName);
+
+			String physicalPath = (String) conf.get("rootPath") + savePath;
+
+			InputStream is = fileStream.openStream();
+			State storageState = StorageManager.saveFileByInputStream(is,
+					physicalPath, maxSize);
+			is.close();
+
+			if (storageState.isSuccess()) {
+				storageState.putInfo("url", PathFormat.format(savePath));
+				storageState.putInfo("type", suffix);
+				storageState.putInfo("original", originFileName + suffix);
+			}
+
+			return storageState;
+		} catch (FileUploadException e) {
+			return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
+		} catch (IOException e) {
+		}
+		return new BaseState(false, AppInfo.IO_ERROR);
+	}
+
+	private static boolean validType(String type, String[] allowTypes) {
+		List<String> list = Arrays.asList(allowTypes);
+
+		return list.contains(type);
+	}*/
+}

+ 155 - 0
src/main/java/com/baidu/ueditor/upload/CopyOfStorageManager.java

@@ -0,0 +1,155 @@
+package com.baidu.ueditor.upload;
+
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.State;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.FileUtils;
+
+public class CopyOfStorageManager {/*
+	public static final int BUFFER_SIZE = 8192;
+
+	public CopyOfStorageManager() {
+	}
+
+	public static State saveBinaryFile(byte[] data, String path) {
+		File file = new File(path);
+
+		State state = valid(file);
+
+		if (!state.isSuccess()) {
+			return state;
+		}
+
+		try {
+			BufferedOutputStream bos = new BufferedOutputStream(
+					new FileOutputStream(file));
+			bos.write(data);
+			bos.flush();
+			bos.close();
+		} catch (IOException ioe) {
+			return new BaseState(false, AppInfo.IO_ERROR);
+		}
+
+		state = new BaseState(true, file.getAbsolutePath());
+		state.putInfo( "size", data.length );
+		state.putInfo( "title", file.getName() );
+		return state;
+	}
+
+	public static State saveFileByInputStream(InputStream is, String path,
+			long maxSize) {
+		State state = null;
+
+		File tmpFile = getTmpFile();
+
+		byte[] dataBuf = new byte[ 2048 ];
+		BufferedInputStream bis = new BufferedInputStream(is, CopyOfStorageManager.BUFFER_SIZE);
+
+		try {
+			BufferedOutputStream bos = new BufferedOutputStream(
+					new FileOutputStream(tmpFile), CopyOfStorageManager.BUFFER_SIZE);
+
+			int count = 0;
+			while ((count = bis.read(dataBuf)) != -1) {
+				bos.write(dataBuf, 0, count);
+			}
+			bos.flush();
+			bos.close();
+
+			if (tmpFile.length() > maxSize) {
+				tmpFile.delete();
+				return new BaseState(false, AppInfo.MAX_SIZE);
+			}
+
+			state = saveTmpFile(tmpFile, path);
+
+			if (!state.isSuccess()) {
+				tmpFile.delete();
+			}
+
+			return state;
+			
+		} catch (IOException e) {
+		}
+		return new BaseState(false, AppInfo.IO_ERROR);
+	}
+
+	public static State saveFileByInputStream(InputStream is, String path) {
+		State state = null;
+
+		File tmpFile = getTmpFile();
+
+		byte[] dataBuf = new byte[ 2048 ];
+		BufferedInputStream bis = new BufferedInputStream(is, CopyOfStorageManager.BUFFER_SIZE);
+
+		try {
+			BufferedOutputStream bos = new BufferedOutputStream(
+					new FileOutputStream(tmpFile), CopyOfStorageManager.BUFFER_SIZE);
+
+			int count = 0;
+			while ((count = bis.read(dataBuf)) != -1) {
+				bos.write(dataBuf, 0, count);
+			}
+			bos.flush();
+			bos.close();
+
+			state = saveTmpFile(tmpFile, path);
+
+			if (!state.isSuccess()) {
+				tmpFile.delete();
+			}
+
+			return state;
+		} catch (IOException e) {
+		}
+		return new BaseState(false, AppInfo.IO_ERROR);
+	}
+
+	private static File getTmpFile() {
+		File tmpDir = FileUtils.getTempDirectory();
+		String tmpFileName = (Math.random() * 10000 + "").replace(".", "");
+		return new File(tmpDir, tmpFileName);
+	}
+
+	private static State saveTmpFile(File tmpFile, String path) {
+		State state = null;
+		File targetFile = new File(path);
+
+		if (targetFile.canWrite()) {
+			return new BaseState(false, AppInfo.PERMISSION_DENIED);
+		}
+		try {
+			FileUtils.moveFile(tmpFile, targetFile);
+		} catch (IOException e) {
+			return new BaseState(false, AppInfo.IO_ERROR);
+		}
+
+		state = new BaseState(true);
+		state.putInfo( "size", targetFile.length() );
+		state.putInfo( "title", targetFile.getName() );
+		
+		return state;
+	}
+
+	private static State valid(File file) {
+		File parentPath = file.getParentFile();
+
+		if ((!parentPath.exists()) && (!parentPath.mkdirs())) {
+			return new BaseState(false, AppInfo.FAILED_CREATE_FILE);
+		}
+
+		if (!parentPath.canWrite()) {
+			return new BaseState(false, AppInfo.PERMISSION_DENIED);
+		}
+
+		return new BaseState(true);
+	}
+*/}

+ 247 - 0
src/main/java/com/baidu/ueditor/upload/StorageManager.java

@@ -0,0 +1,247 @@
+package com.baidu.ueditor.upload;
+
+import com.baidu.ueditor.define.AppInfo;
+import com.baidu.ueditor.define.BaseState;
+import com.baidu.ueditor.define.State;
+import com.key.common.plugs.aliyun.AliyunOSS;
+import com.key.common.plugs.baiduyun.BaiduBOS;
+import com.key.common.utils.DiaowenProperty;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.FileUtils;
+
+public class StorageManager {
+	public static final int BUFFER_SIZE = 8192;
+	
+	public StorageManager() {
+		
+	}
+	
+	public static State saveBinaryFile(byte[] data, String rootPath, String path) {
+		
+		if("local".equals(DiaowenProperty.DWSTORAGETYPE)){
+//			File file = new File(path);
+			File file = new File(rootPath+path);
+			State state = valid(file);
+			if (!state.isSuccess()) {
+				return state;
+			}
+			try {
+				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
+				bos.write(data);
+				bos.flush();
+				bos.close();
+				
+			} catch (IOException ioe) {
+				return new BaseState(false, AppInfo.IO_ERROR);
+			}
+
+			state = new BaseState(true, file.getAbsolutePath());
+			state.putInfo( "size", data.length );
+			state.putInfo( "title", file.getName() );
+			return state;
+		}else{
+			return saveBinaryFileToYun(data, path);
+		}
+		
+	}
+	
+
+	public static State saveFileByInputStream(InputStream is, String rootPath, String path,
+			long maxSize) {
+		if("local".equals(DiaowenProperty.DWSTORAGETYPE)){
+			State state = null;
+
+			File tmpFile = getTmpFile();
+			byte[] dataBuf = new byte[ 2048 ];
+			BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE);
+			try {
+				BufferedOutputStream bos = new BufferedOutputStream(
+						new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
+
+				int count = 0;
+				while ((count = bis.read(dataBuf)) != -1) {
+					bos.write(dataBuf, 0, count);
+				}
+				bos.flush();
+				bos.close();
+
+				if (tmpFile.length() > maxSize) {
+					tmpFile.delete();
+					return new BaseState(false, AppInfo.MAX_SIZE);
+				}
+
+				state = saveTmpFile(tmpFile, rootPath+path);
+
+				if (!state.isSuccess()) {
+					tmpFile.delete();
+				}
+
+				return state;
+				
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			return new BaseState(false, AppInfo.IO_ERROR);	
+		}else{
+			return saveFileByInputStreamToYun(is, path);
+		}
+	}
+
+	public static State saveFileByInputStream(InputStream is,String rootPath, String path) {
+		if("local".equals(DiaowenProperty.DWSTORAGETYPE)){
+			State state = null;
+
+			File tmpFile = getTmpFile();
+
+			byte[] dataBuf = new byte[ 2048 ];
+			BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE);
+
+			try {
+				BufferedOutputStream bos = new BufferedOutputStream(
+						new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
+
+				int count = 0;
+				while ((count = bis.read(dataBuf)) != -1) {
+					bos.write(dataBuf, 0, count);
+				}
+				bos.flush();
+				bos.close();
+
+				state = saveTmpFile(tmpFile, rootPath+path);
+
+				if (!state.isSuccess()) {
+					tmpFile.delete();
+				}
+				return state;
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			return new BaseState(false, AppInfo.IO_ERROR);
+		}else{
+			return saveFileByInputStreamToYun(is, path);
+		}
+	
+	}
+	
+
+	private static File getTmpFile() {
+		File tmpDir = FileUtils.getTempDirectory();
+		String tmpFileName = (Math.random() * 10000 + "").replace(".", "");
+		return new File(tmpDir, tmpFileName);
+	}
+
+	private static State saveTmpFile(File tmpFile, String path) {
+		State state = null;
+		File targetFile = new File(path);
+
+		if (targetFile.canWrite()) {
+			return new BaseState(false, AppInfo.PERMISSION_DENIED);
+		}
+		try {
+			FileUtils.moveFile(tmpFile, targetFile);
+		} catch (IOException e) {
+			e.printStackTrace();
+			return new BaseState(false, AppInfo.IO_ERROR);
+		}
+
+		state = new BaseState(true);
+		state.putInfo( "size", targetFile.length() );
+		state.putInfo( "title", targetFile.getName() );
+		
+		return state;
+	}
+
+	private static State valid(File file) {
+		File parentPath = file.getParentFile();
+
+		if ((!parentPath.exists()) && (!parentPath.mkdirs())) {
+			return new BaseState(false, AppInfo.FAILED_CREATE_FILE);
+		}
+
+		if (!parentPath.canWrite()) {
+			return new BaseState(false, AppInfo.PERMISSION_DENIED);
+		}
+
+		return new BaseState(true);
+	}
+
+	
+	
+	/**
+	 * SaveToYun
+	 */
+	
+
+	public static State saveBinaryFileToYun(byte[] data, String savePath) {
+		State state = null;
+		
+		File tmpFile = getTmpFile();
+		
+		try {
+			BufferedOutputStream bos = new BufferedOutputStream(
+					new FileOutputStream(tmpFile));
+			bos.write(data);
+			bos.flush();
+			bos.close();
+			
+			
+			if("aliyunOSS".equals(DiaowenProperty.DWSTORAGETYPE)){
+				// 阿里云支持 将文件写入到aliyun oss
+				AliyunOSS.putObject(DiaowenProperty.UPLOADFILE_BACKET, tmpFile, savePath);
+				tmpFile.delete();	
+			}else if("baiduBOS".equals(DiaowenProperty.DWSTORAGETYPE)){
+				BaiduBOS.putObject(DiaowenProperty.UPLOADFILE_BACKET,tmpFile, savePath);
+				tmpFile.delete();
+			}
+			
+			
+		} catch (IOException ioe) {
+			ioe.printStackTrace();
+			return new BaseState(false, AppInfo.IO_ERROR);
+		}
+
+		state = new BaseState(true, tmpFile.getAbsolutePath());
+		state.putInfo( "size", data.length );
+		state.putInfo( "title", tmpFile.getName() );
+		return state;
+	}
+	
+
+	public static State saveFileByInputStreamToYun(InputStream inputStream,
+			String savePath) {
+		State state = null;
+		
+		savePath=savePath.substring(1);
+		
+		try {
+//			AliyunOSS.pubObjects(AliyunOSS.UPLOADFILE_BACKET, inputStream, savePath);
+
+			if("aliyunOSS".equals(DiaowenProperty.DWSTORAGETYPE)){
+				// 阿里云支持 将文件写入到aliyun oss
+				AliyunOSS.putObject(DiaowenProperty.UPLOADFILE_BACKET, inputStream, savePath);
+			}else if("baiduBOS".equals(DiaowenProperty.DWSTORAGETYPE)){
+				BaiduBOS.putObject(DiaowenProperty.UPLOADFILE_BACKET,inputStream, savePath);
+			}
+			
+			state = new BaseState(true);
+			
+			//state.putInfo( "size", inputStream.length() );
+//			state.putInfo( "title", inputStream.getName() );
+			return state;
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return new BaseState(false, AppInfo.IO_ERROR);
+	}
+	
+
+}

+ 29 - 0
src/main/java/com/baidu/ueditor/upload/Uploader.java

@@ -0,0 +1,29 @@
+package com.baidu.ueditor.upload;
+
+import com.baidu.ueditor.define.State;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+
+public class Uploader {
+	private HttpServletRequest request = null;
+	private Map<String, Object> conf = null;
+
+	public Uploader(HttpServletRequest request, Map<String, Object> conf) {
+		this.request = request;
+		this.conf = conf;
+	}
+
+	public final State doExec() {
+		String filedName = (String) this.conf.get("fieldName");
+		State state = null;
+
+		if ("true".equals(this.conf.get("isBase64"))) {
+			state = Base64Uploader.save(this.request.getParameter(filedName),
+					this.conf);
+		} else {
+			state = BinaryUploader.save(this.request, this.conf);
+		}
+
+		return state;
+	}
+}

+ 38 - 0
src/main/java/com/key/common/CheckType.java

@@ -0,0 +1,38 @@
+package com.key.common;
+
+public enum CheckType {
+	NO("无验证", 0), 
+	EMAIL("Email", 1), 
+	STRLEN("字符长度", 2), 
+	UNSTRCN("禁止中文", 3),
+	STRCN("仅许中文", 4),
+	NUM("数值", 5),
+	TELENUM("电话号码", 6),
+	PHONENUM("手机号码", 7),
+	DATE("日期", 8),
+	IDENTCODE("身份证号", 9),
+	ZIPCODE("邮政编码", 10),
+	URL("网址", 11),
+	TELE_PHONE_NUM("电话或手机号", 12);
+	
+	private String name;
+	private int index;
+	private CheckType(String name,int index){
+		this.name=name;
+		this.index=index;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public int getIndex() {
+		return index;
+	}
+	public void setIndex(int index) {
+		this.index = index;
+	}
+	
+	
+}

+ 65 - 0
src/main/java/com/key/common/QuType.java

@@ -0,0 +1,65 @@
+package com.key.common;
+
+public enum QuType {
+
+	YESNO("是非题","yesno", 0), 
+	RADIO("单选题","radio", 1), 
+	CHECKBOX("多选题","checkbox", 2), 
+	FILLBLANK("填空题","fillblank", 3),
+	
+	COMPRADIO("复合单选","comp-radio", 17), 
+	COMPCHECKBOX("复合多选","comp-checkbox", 18), 
+	
+	MULTIFILLBLANK("多项填空题","multi-fillblank", 4),//组合填空题
+	ANSWER("多行填空题","answer", 5),//原问答题
+	BIGQU("大题","bigqu", 6),
+	
+	ENUMQU("枚举题","enumqu", 7),
+	SCORE("评分题","score", 8),
+	ORDERQU("排序题","orderby", 9), 
+	PROPORTION ("比重题","proportion", 10), 
+	CHENRADIO("矩阵单选题","chen-radio", 11), 
+	CHENFBK("矩阵填空题","chen-fbk", 12), 
+	CHENCHECKBOX("矩阵多选题","chen-checkbox", 13),
+	COMPCHENRADIO("复合矩阵单选题","comp-chen-radio", 14), 
+	
+	UPLOADFILE("文件上传题","sendfile",15),
+	PAGETAG("分页标记","pagetag",16),
+	PARAGRAPH("段落说明","paragraph",17),
+	CHENSCORE("矩阵评分题","chen-score", 18);
+	
+	private String cnName;
+	private String actionName;
+	private int index;
+	
+	QuType(String cnName,String actionName,int index){
+		this.cnName=cnName;
+		this.actionName=actionName;
+		this.index=index;
+	}
+
+	public String getCnName() {
+		return cnName;
+	}
+
+	public void setCnName(String cnName) {
+		this.cnName = cnName;
+	}
+
+	public String getActionName() {
+		return actionName;
+	}
+
+	public void setActionName(String actionName) {
+		this.actionName = actionName;
+	}
+
+	public int getIndex() {
+		return index;
+	}
+
+	public void setIndex(int index) {
+		this.index = index;
+	}
+	
+}

+ 50 - 0
src/main/java/com/key/common/YesnoOption.java

@@ -0,0 +1,50 @@
+package com.key.common;
+
+public enum YesnoOption {
+	
+	OPTION1("是","否",0),
+	OPTION2("对","错",1),
+	OPTION3("正确","错误",2),
+	OPTION4("同意","不同意",4),
+	OPTION5("满意","不满意",5),
+	OPTION6("喜欢","不喜欢",6),
+	OPTION7("支持","反对", 7),
+	OPTION8("Ture","False", 8), 
+	OPTION9("Yes","No",9); 
+	
+	private String trueValue;
+	private String falseValue;
+	private int index;
+	
+	YesnoOption(String trueValue,String falseValue,int index) {
+		this.trueValue=trueValue;
+		this.falseValue=falseValue;
+		this.index=index;
+	}
+
+	public String getTrueValue() {
+		return trueValue;
+	}
+
+	public void setTrueValue(String trueValue) {
+		this.trueValue = trueValue;
+	}
+
+	public String getFalseValue() {
+		return falseValue;
+	}
+
+	public void setFalseValue(String falseValue) {
+		this.falseValue = falseValue;
+	}
+
+	public int getIndex() {
+		return index;
+	}
+
+	public void setIndex(int index) {
+		this.index = index;
+	}
+	
+	
+}

+ 131 - 0
src/main/java/com/key/common/base/action/CrudActionSupport.java

@@ -0,0 +1,131 @@
+package com.key.common.base.action;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.key.common.plugs.page.Page;
+import com.key.common.plugs.page.PropertyFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.key.common.base.entity.IdEntity;
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.ModelDriven;
+import com.opensymphony.xwork2.Preparable;
+
+/**
+ * Struts2中典型CRUD Action的抽象基类.
+ * 
+ * 主要定义了对Preparable,ModelDriven接口的使用,以及CRUD函数和返回值的命名.
+ *
+ * @param <T> CRUDAction所管理的对象类型.
+ * 
+ */
+public abstract class CrudActionSupport<T extends IdEntity,ID extends Serializable> extends ActionSupport implements ModelDriven<T>, Preparable {
+
+	private static final long serialVersionUID = -3250152265646142566L;
+
+	/**
+	 * 进行增删改操作后,以redirect方式重新打开action默认页的result名.
+	 */
+	public static final String RELOAD = "reload";
+
+	protected Logger logger = LoggerFactory.getLogger(getClass());
+
+	/**
+	 * Action函数, 默认的action函数, 默认调用list()函数.
+	 */
+	@Override
+	public String execute() throws Exception {
+		return list();
+	}
+
+	//-- CRUD Action函数 --//
+	/**
+	 * Action函数, 显示Entity列表.
+	 * 建议return SUCCESS.
+	 */
+//	public abstract String list() throws Exception;
+	public String list() throws Exception{return SUCCESS;};
+
+	/**
+	 * Action函数,显示新增或修改Entity界面.
+	 * 建议return INPUT.
+	 */
+	@Override
+//	public abstract String input() throws Exception;
+	public String input() throws Exception{return INPUT;};
+
+	/**
+	 * Action函数,新增或修改Entity. 
+	 * 建议return RELOAD.
+	 */
+//	public abstract String save() throws Exception;
+	public String save() throws Exception{return RELOAD;};
+
+	/**
+	 * Action函数,删除Entity.
+	 * 建议return RELOAD.
+	 */
+//	public abstract String delete() throws Exception;
+	public String delete() throws Exception{return RELOAD;};
+
+	//-- Preparable函数 --//
+	/**
+	 * 实现空的prepare()函数,屏蔽所有Action函数公共的二次绑定.
+	 */
+	@Override
+	public void prepare() throws Exception {
+	}
+
+	/**
+	 * 在input()前执行二次绑定.
+	 */
+	public void prepareInput() throws Exception {
+		System.out.println("二次绑定....");
+		prepareModel();
+	}
+
+	/**
+	 * 在save()前执行二次绑定.
+	 */
+	public void prepareSave() throws Exception {
+		prepareModel();
+	}
+
+	/**
+	 * 等同于prepare()的内部函数,供prepardMethodName()函数调用. 
+	 */
+//	protected abstract void prepareModel() throws Exception;
+	protected void prepareModel() throws Exception{};
+
+	protected T entity;
+	
+	protected ID id;
+
+	public ID getId() {
+		return id;
+	}
+
+	public void setId(ID id) {
+		this.id = id;
+	}
+	
+	protected List<PropertyFilter> filters=new ArrayList<PropertyFilter>();
+	protected Page<T> page=new Page<T>();
+
+	public Page<T> getPage() {
+		return page;
+	}
+
+	public void setPage(Page<T> page) {
+		this.page = page;
+	}
+	
+	@Override
+	public T getModel() {
+		return entity;
+	}
+	
+}

+ 123 - 0
src/main/java/com/key/common/base/action/JcaptchaAction.java

@@ -0,0 +1,123 @@
+package com.key.common.base.action;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.convention.annotation.Namespace;
+import org.apache.struts2.convention.annotation.Namespaces;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.key.common.utils.web.Struts2Utils;
+import com.octo.captcha.service.image.ImageCaptchaService;
+import com.opensymphony.xwork2.ActionSupport;
+import com.sun.image.codec.jpeg.JPEGCodec;
+import com.sun.image.codec.jpeg.JPEGImageEncoder;
+
+@Namespaces({ @Namespace("/") })
+public class JcaptchaAction extends ActionSupport {
+	
+	@Autowired  
+    private ImageCaptchaService imageCaptchaService;  
+	
+	public String execute() throws Exception {
+		HttpServletRequest request = Struts2Utils.getRequest();
+		HttpServletResponse response = Struts2Utils.getResponse();
+        byte[] captchaChallengeAsJpeg = null;  
+        // the output stream to render the captcha image as jpeg into  
+        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();  
+        try {  
+            // get the session id that will identify the generated captcha.  
+            // the same id must be used to validate the response, the session id  
+            // is a good candidate!  
+            String captchaId = request.getSession().getId();  
+            // call the ImageCaptchaService getChallenge method  
+            BufferedImage challenge = imageCaptchaService.getImageChallengeForID(captchaId, request.getLocale());
+            // a jpeg encoder  
+            JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream);  
+            jpegEncoder.encode(challenge);
+        } catch (Exception e) {  
+            // TODO Auto-generated catch block  
+            e.printStackTrace();  
+        }
+        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();    
+        // flush it in the response    
+        response.setHeader("Cache-Control", "no-store");
+        response.setHeader("Pragma", "no-cache");
+        response.setDateHeader("Expires", 0);
+        response.setContentType("image/jpeg");
+        ServletOutputStream responseOutputStream = response.getOutputStream();
+        responseOutputStream.write(captchaChallengeAsJpeg);
+        responseOutputStream.flush();
+        responseOutputStream.close();
+        return null;
+	}  
+	
+	
+	/*@Autowired
+	private GenericManageableCaptchaService captchaService;
+
+	@Override
+	public String execute() throws Exception {
+		HttpServletRequest request = Struts2Utils.getRequest();
+		HttpServletResponse response = Struts2Utils.getResponse();
+		byte[] captchaChallengeAsJpeg = null;
+		// 输出jpg的字节流
+		ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
+		try {
+			String captchaId = request.getSession().getId();
+			// call the ImageCaptchaService getChallenge method
+			BufferedImage challenge = (BufferedImage) captchaService
+					.getChallengeForID(captchaId, request.getLocale());
+			JPEGImageEncoder jpegEncoder = JPEGCodec
+					.createJPEGEncoder(jpegOutputStream);
+			jpegEncoder.encode(challenge);
+
+		} catch (IllegalArgumentException e) {
+			response.sendError(response.SC_NOT_FOUND);
+			return null;
+		} catch (CaptchaServiceException e) {
+			response.sendError(response.SC_INTERNAL_SERVER_ERROR);
+			return null;
+		}
+		System.out.println("resImg..");
+		captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
+		// flush it in the response
+		response.setHeader("Cache-Control", "no-store");
+		response.setHeader("Pragma", "no-cache");
+		response.setDateHeader("Expires", 0);
+		response.setContentType("image/jpeg");
+		ServletOutputStream responseOutputStream = response.getOutputStream();
+		responseOutputStream.write(captchaChallengeAsJpeg);
+		responseOutputStream.flush();
+		responseOutputStream.close();
+		return null;
+	}
+	
+	*//**
+	 * 适用ajax异步请求判断验证码对与不对
+	 *//*
+	public String ajaxCheckCode() throws Exception{
+		HttpServletRequest request=Struts2Utils.getRequest();
+		HttpServletResponse response=Struts2Utils.getResponse();
+		String code = request.getParameter("code");
+		System.out.println("code:"+code);
+		String result="true";
+		try{
+			if (!captchaService.validateResponseForID(request.getSession().getId(),code)){
+				//验证码不正确
+				result="false";
+			}
+		}catch (Exception e) {
+			e.printStackTrace();
+		}
+		PrintWriter out=response.getWriter();
+		out.write(result);
+		System.out.println("result..."+result);
+		return null;
+	}
+*/
+}

+ 259 - 0
src/main/java/com/key/common/base/action/UploadAction.java

@@ -0,0 +1,259 @@
+package com.key.common.base.action;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Random;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.key.common.plugs.aliyun.AliyunOSS;
+import com.key.common.plugs.baiduyun.BaiduBOS;
+import com.key.common.utils.DiaowenProperty;
+import com.key.common.utils.web.Struts2Utils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.struts2.convention.annotation.AllowedMethods;
+import org.apache.struts2.convention.annotation.Namespace;
+import org.apache.struts2.convention.annotation.Namespaces;
+import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
+
+import com.key.common.utils.FileUtils;
+import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.dispatcher.multipart.StrutsUploadedFile;
+import org.apache.struts2.dispatcher.multipart.UploadedFile;
+
+@Namespaces(@Namespace("/up"))
+@AllowedMethods({"saveimage","saveFile","saveUpFile"})
+public class UploadAction extends ActionSupport{
+	
+	private static final long serialVersionUID = -7990272086028152723L;
+
+	private File[] files;
+	private String[] fileNames;
+	private String[] uploadContentTypes;
+
+	/***
+	 * 上传图片数据,非安全存储
+	 * @return
+	 * @throws Exception
+	 */
+	public String saveimage() throws Exception {
+//		System.out.println("saveimgage");
+		StringBuffer sb = new StringBuffer();
+		HttpServletResponse response = Struts2Utils.getResponse();
+		try {
+			HttpServletRequest request = Struts2Utils.getRequest();
+			String rootPath = request.getSession().getServletContext()
+					.getRealPath("/");
+			String savePath = "file" + File.separator + "images" + File.separator;
+
+			if (files != null && files.length > 0) {
+
+				String[] newNames = null;
+
+				if("aliyunOSS".equals(DiaowenProperty.DWSTORAGETYPE) || "baiduBOS".equals(DiaowenProperty.DWSTORAGETYPE)){
+					newNames = saveFileToYun(savePath, files, fileNames, false);
+				}else {
+					newNames = FileUtils.transferFile2(rootPath+File.separator+savePath, files, fileNames);
+				}
+				
+				sb.append("{\"success\":\"true\"");
+				sb.append(",\"filename\":\"");
+				for (int i = 0; i < files.length; i++) {
+					sb.append(fileNames[i]);
+					sb.append("  ");
+				}
+				sb.append("\"");
+				sb.append(",\"location\":\"");
+				for (int i = 0; i < newNames.length; i++) {
+					sb.append("/file/images/" + newNames[i]+ ";");
+				}
+				if(sb!=null&&StringUtils.isNotBlank(sb.toString())&&sb.toString().endsWith(";")){
+					sb.deleteCharAt(sb.length()-1);
+				}
+				sb.append("\"");
+			}
+			
+			sb.append("}");
+		} catch (Exception e) {
+			sb.append("{\"success\":\"false\",\"error\":\"上传失败\"}");
+			e.printStackTrace();
+		}
+		response.setHeader("Content-Type", "text/plain;charset=UTF-8");
+		response.getWriter().print(sb.toString());
+		response.getWriter().close();
+		return null;
+	}
+
+	/**
+	 * 上传文件数据,非安全存储
+	 **/
+	public String saveFile() throws Exception {
+		StringBuffer sb = new StringBuffer();
+		HttpServletResponse response = Struts2Utils.getResponse();
+		try {
+			HttpServletRequest request = Struts2Utils.getRequest();
+			MultiPartRequestWrapper multipartRequest = (MultiPartRequestWrapper) request;
+
+			String basePath=request.getParameter("basepath");
+			String rootPath = request.getSession().getServletContext().getRealPath("/");
+			String savePath = "file" + File.separator + basePath + File.separator;
+
+			if (files != null && files.length > 0) {
+
+//				String[] newNames = FileUtils.transferFile2(savePath, files,fileNames);
+				String[] newNames = null;
+				
+				if("aliyunOSS".equals(DiaowenProperty.DWSTORAGETYPE) || "baiduBOS".equals(DiaowenProperty.DWSTORAGETYPE)){
+					newNames = saveFileToYun(savePath, files, fileNames, false);
+				}else {
+					newNames = FileUtils.transferFile2( rootPath+File.separator+savePath, files, fileNames);
+				}
+				
+				sb.append("{\"success\":\"true\"");
+				sb.append(",\"filename\":\"");
+				for (int i = 0; i < files.length; i++) {
+					sb.append(fileNames[i]);
+					sb.append("  ");
+				}
+				sb.append("\"");
+				sb.append(",\"location\":\"");
+				for (int i = 0; i < newNames.length; i++) {
+					sb.append("/file/"+basePath+"/" + newNames[i]+ ";");
+				}
+				if(sb!=null&&StringUtils.isNotBlank(sb.toString())&&sb.toString().endsWith(";")){
+					sb.deleteCharAt(sb.length()-1);
+				}
+				sb.append("\"");
+			}
+			sb.append("}");
+		} catch (Exception e) {
+			sb.append("{\"success\":\"false\",\"error\":\"上传失败\"}");
+			e.printStackTrace();
+		}
+		response.setHeader("Content-Type", "text/plain;charset=UTF-8");
+		response.getWriter().print(sb.toString());
+		response.getWriter().close();
+		return null;
+	}
+	
+	
+	/**
+	 * 上传文件数据,安全存储
+	 * /WebRoot/WEB-INF/upfile
+	 */
+	public String saveUpFile() throws Exception {
+		StringBuffer sb = new StringBuffer();
+		HttpServletResponse response = Struts2Utils.getResponse();
+		try {
+			HttpServletRequest request = Struts2Utils.getRequest();
+			MultiPartRequestWrapper multipartRequest = (MultiPartRequestWrapper) request;
+			String basePath=request.getParameter("basepath");
+			String rootPath = request.getSession().getServletContext().getRealPath("/");
+			String savePath = "WEB-INF"+File.separator+"upfile" + File.separator;
+
+			if (files != null && files.length > 0) {
+
+//				String[] newNames = FileUtils.transferFile2(savePath, files,fileNames);
+				String[] newNames = null;
+				if("aliyunOSS".equals(DiaowenProperty.DWSTORAGETYPE) || "baiduBOS".equals(DiaowenProperty.DWSTORAGETYPE)){
+					newNames = saveFileToYun(savePath, files, fileNames, true);
+				}else {
+					newNames = FileUtils.transferFile2(rootPath+savePath, files, fileNames);
+				}
+				
+				sb.append("{\"success\":\"true\"");
+				sb.append(",\"filename\":\"");
+				for (int i = 0; i < files.length; i++) {
+					sb.append(fileNames[i]);
+					sb.append("  ");
+				}
+				sb.append("\"");
+				sb.append(",\"location\":\"");
+				for (int i = 0; i < newNames.length; i++) {
+					sb.append("/WEB-INF/upfile/" + newNames[i]+ ";");
+				}
+				if(sb!=null&&StringUtils.isNotBlank(sb.toString())&&sb.toString().endsWith(";")){
+					sb.deleteCharAt(sb.length()-1);
+				}
+				sb.append("\"");
+			}
+			sb.append("}");
+		} catch (Exception e) {
+			sb.append("{\"success\":\"false\",\"error\":\"上传失败\"}");
+			e.printStackTrace();
+		}
+		response.setHeader("Content-Type", "text/plain;charset=UTF-8");
+		response.getWriter().print(sb.toString());
+//		response.getWriter().close();
+		return null;
+	}
+	
+	private static String[] saveFileToYun(String path, File[] files, String[] filenames, boolean isJm)
+			throws IllegalStateException, IOException {
+		if (files != null && files.length > 0) {
+			String[] temp=new String[files.length];
+			char[] str = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+					'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+					'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+					'8', '9' };
+			for (int i = 0; i < files.length; i++) {
+				try {
+					StringBuffer fileName = new StringBuffer("");
+					Random r = new Random();
+					int pos = -1;
+					for (int j = 0; j < 15; j++) {
+						pos = Math.abs(r.nextInt(36));
+						fileName.append(str[pos]);
+					}
+					fileName.append(filenames[i].substring(filenames[i].lastIndexOf(".")));
+					System.out.println("path:"+path);
+					
+					if("aliyunOSS".equals(DiaowenProperty.DWSTORAGETYPE)){
+						//保存到aliyun
+						if(isJm){
+							AliyunOSS.putObject(DiaowenProperty.UPLOADFILE_JM_BACKET, files[i], path + fileName.toString());
+						}else{
+							AliyunOSS.putObject(DiaowenProperty.UPLOADFILE_BACKET, files[i], path + fileName.toString());
+						}
+					}else if("baiduBOS".equals(DiaowenProperty.DWSTORAGETYPE)){
+						//保存到aliyun
+						if(isJm){
+							BaiduBOS.putObject(DiaowenProperty.UPLOADFILE_JM_BACKET, files[i], path + fileName.toString());
+						}else{
+							BaiduBOS.putObject(DiaowenProperty.UPLOADFILE_BACKET, files[i], path + fileName.toString());
+						}
+					}
+					temp[i]=fileName.toString();
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+				
+			}
+			return temp;
+		}
+		return null;
+	}
+
+
+	public File[] getUploadify() {
+		return this.files;
+	}
+	public void setUploadify(File[] upload) {
+		this.files = upload;
+	}
+	public String[] getUploadifyFileName() {
+		return this.fileNames;
+	}
+	public void setUploadifyFileName(String[] uploadFileName) {
+		this.fileNames = uploadFileName;
+	}
+	public String[] getUploadifyContentType() {
+		return this.uploadContentTypes;
+	}
+	public void setUploadifyContentType(String[] uploadContentType) {
+		this.uploadContentTypes = uploadContentType;
+	}
+	
+	
+}

+ 18 - 0
src/main/java/com/key/common/base/dao/UserDao.java

@@ -0,0 +1,18 @@
+package com.key.common.base.dao;
+
+import com.key.common.base.entity.User;
+import com.key.common.dao.BaseDao;
+import com.key.common.plugs.page.Page;
+
+
+/**
+ * @author keyuan(keyuan258@gmail.com)
+ *
+ * https://github.com/wkeyuan/DWSurvey
+ * http://dwsurvey.net
+ */
+public interface UserDao extends BaseDao<User, String> {
+
+	public void resetUserGroup(String groupId);
+	
+}

+ 29 - 0
src/main/java/com/key/common/base/dao/UserDaoImpl.java

@@ -0,0 +1,29 @@
+package com.key.common.base.dao;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import com.key.common.base.entity.User;
+import com.key.common.dao.BaseDaoImpl;
+import com.key.common.plugs.page.Page;
+import org.hibernate.SQLQuery;
+import org.springframework.stereotype.Repository;
+
+
+/**
+ * @author keyuan(keyuan258@gmail.com)
+ *
+ * https://github.com/wkeyuan/DWSurvey
+ * http://dwsurvey.net
+ */
+@Repository
+public class UserDaoImpl extends BaseDaoImpl<User, String> implements UserDao{
+
+	@Override
+	public void resetUserGroup(String groupId) {
+		String sql="UPDATE t_user SET user_group_id = '' WHERE id = id";
+		this.getSession().createSQLQuery(sql).executeUpdate();
+	}
+	
+}

+ 39 - 0
src/main/java/com/key/common/base/entity/IdEntity.java

@@ -0,0 +1,39 @@
+package com.key.common.base.entity;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+
+import org.hibernate.annotations.GenericGenerator;
+
+/**
+ * 统一定义id的entity基类.
+ * 
+ * 基类统一定义id的属性名称、数据类型、列名映射及生成策略.
+ * 子类可重载getId()函数重定义id的列名映射和生成策略.
+ * 
+ */
+//JPA Entity基类的标识
+@MappedSuperclass
+public abstract class IdEntity {//implements Serializable
+
+	protected String id;
+
+	@Id
+//	@GeneratedValue(strategy = GenerationType.AUTO)
+	@GeneratedValue(generator = "system-uuid")
+	@GenericGenerator(name = "system-uuid", strategy = "uuid")
+    @Column(length = 55)
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+}

+ 34 - 0
src/main/java/com/key/common/base/entity/IdLongEntity.java

@@ -0,0 +1,34 @@
+package com.key.common.base.entity;
+
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+
+/**
+ * 统一定义id的entity基类.
+ * 
+ * 基类统一定义id的属性名称、数据类型、列名映射及生成策略.
+ * 子类可重载getId()函数重定义id的列名映射和生成策略.
+ *
+ */
+//JPA Entity基类的标识
+@MappedSuperclass
+public abstract class IdLongEntity {
+
+	protected Long id;
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.AUTO)
+	//@GeneratedValue(strategy = GenerationType.AUTO, generator = "uuid-string")
+	//@GeneratedValue(generator = "system-uuid")
+    //@GenericGenerator(name = "system-uuid", strategy = "uuid")
+    //@Column(length = 32)
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+}

+ 76 - 0
src/main/java/com/key/common/base/entity/Tracker.java

@@ -0,0 +1,76 @@
+package com.key.common.base.entity;
+
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+/**
+ * 
+ * @author KeYuan
+ * @date 2013下午10:01:45
+ *
+ */
+@Entity
+@Table(name = "tracker")
+public class Tracker extends IdEntity {
+
+	private String dataType;
+	private String dataId;
+	private String operation;
+	private Date optime = new Date();
+	private String loginName;
+
+	public Tracker() {
+		super();
+	}
+
+	public Tracker(String dataType, String dataId, String operation, String loginName) {
+		super();
+		this.dataType = dataType;
+		this.dataId = dataId;
+		this.operation = operation;
+		this.loginName = loginName;
+	}
+
+	public String getDataType() {
+		return dataType;
+	}
+
+	public void setDataType(String dataType) {
+		this.dataType = dataType;
+	}
+
+	public String getDataId() {
+		return dataId;
+	}
+
+	public void setDataId(String dataId) {
+		this.dataId = dataId;
+	}
+
+	public String getOperation() {
+		return operation;
+	}
+
+	public void setOperation(String operation) {
+		this.operation = operation;
+	}
+
+	public Date getOptime() {
+		return optime;
+	}
+
+	public void setOptime(Date optime) {
+		this.optime = optime;
+	}
+
+	public String getLoginName() {
+		return loginName;
+	}
+
+	public void setLoginName(String loginName) {
+		this.loginName = loginName;
+	}
+	
+}

+ 14 - 0
src/main/java/com/key/common/base/entity/TrackerConstants.java

@@ -0,0 +1,14 @@
+package com.key.common.base.entity;
+
+/**
+ * 
+ * @author KeYuan
+ * @date 2013下午10:01:50
+ *
+ */
+public class TrackerConstants {
+	public static String OPERATION_ADD = "add";
+	public static String OPERATION_DELETE = "delete";
+	public static String OPERATION_UPDATE = "update";
+	public static String OPERATION_SAVE = "save";
+}

+ 248 - 0
src/main/java/com/key/common/base/entity/User.java

@@ -0,0 +1,248 @@
+package com.key.common.base.entity;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+
+import com.key.common.plugs.mapper.CollectionMapper;
+
+/**
+ * 
+ * @author KeYuan
+ * @date 2013下午10:02:00
+ *
+ */
+@Entity
+@Table(name = "T_USER")
+public class User extends IdEntity {
+	private String loginName;
+	private String shaPassword;
+	//用户名
+	private String name;//
+	//邮箱
+	private String email;
+	//出生年月
+	private Date birthday;
+	//最高学历
+	private Integer eduQuali;
+	//性别
+	private Integer sex;
+
+	//2激活 1未激活 0不可用
+	private Integer status=1;// 账号状态
+	private Integer version = 1;//1 默认 2测试
+	private Date createTime = new Date();
+	private String createBy = "";
+	private Date lastLoginTime;
+	private String cellphone;
+	
+	//激活账号CODE
+	private String activationCode;
+	//找回密码code   ""或null表示没有激活找回密码功能
+	private String findPwdCode;
+	//找回密码最后期限  默认设置一天之内
+	private Date findPwdLastDate;
+	
+	//加点盐
+	private String salt;
+
+//	private Date tokenTime;
+	
+	// Hibernate自动维护的Version字段
+	// @Version
+	public Integer getVersion() {
+		return version;
+	}
+
+	public void setVersion(Integer version) {
+		this.version = version;
+	}
+
+	@Column(nullable = false, unique = true)
+	public String getLoginName() {
+		return loginName;
+	}
+
+	public void setLoginName(String loginName) {
+		this.loginName = loginName;
+	}
+
+	public String getShaPassword() {
+		return shaPassword;
+	}
+
+	public void setShaPassword(String shaPassword) {
+		this.shaPassword = shaPassword;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getEmail() {
+		return email;
+	}
+
+	public void setEmail(String email) {
+		this.email = email;
+	}
+
+
+	public Integer getStatus() {
+		return status;
+	}
+
+	public void setStatus(Integer status) {
+		this.status = status;
+	}
+
+	public Date getCreateTime() {
+		return createTime;
+	}
+
+	public void setCreateTime(Date createTime) {
+		this.createTime = createTime;
+	}
+
+	public String getCreateBy() {
+		return createBy;
+	}
+
+	public void setCreateBy(String createBy) {
+		this.createBy = createBy;
+	}
+
+	public String getCellphone() {
+		return cellphone;
+	}
+
+	public void setCellphone(String cellphone) {
+		this.cellphone = cellphone;
+	}
+
+	
+	/*public Long getOrganId() {
+		return organId;
+	}
+
+	public void setOrganId(Long organId) {
+		this.organId = organId;
+	}*/
+
+	public Date getBirthday() {
+		return birthday;
+	}
+
+	public void setBirthday(Date birthday) {
+		this.birthday = birthday;
+	}
+
+	public Integer getEduQuali() {
+		return eduQuali;
+	}
+
+	public void setEduQuali(Integer eduQuali) {
+		this.eduQuali = eduQuali;
+	}
+
+	public Integer getSex() {
+		return sex;
+	}
+
+	public void setSex(Integer sex) {
+		this.sex = sex;
+	}
+
+	public Date getLastLoginTime() {
+		return lastLoginTime;
+	}
+
+	public void setLastLoginTime(Date lastLoginTime) {
+		this.lastLoginTime = lastLoginTime;
+	}
+
+	public String getActivationCode() {
+		return activationCode;
+	}
+
+	public void setActivationCode(String activationCode) {
+		this.activationCode = activationCode;
+	}
+
+	public String getSalt() {
+		return salt;
+	}
+
+	public void setSalt(String salt) {
+		this.salt = salt;
+	}
+	
+	public String getFindPwdCode() {
+		return findPwdCode;
+	}
+
+	public void setFindPwdCode(String findPwdCode) {
+		this.findPwdCode = findPwdCode;
+	}
+
+	public Date getFindPwdLastDate() {
+		return findPwdLastDate;
+	}
+
+	public void setFindPwdLastDate(Date findPwdLastDate) {
+		this.findPwdLastDate = findPwdLastDate;
+	}
+
+
+	private String plainPassword;
+	@Transient
+	public String getPlainPassword() {
+		return plainPassword;
+	}
+
+	public void setPlainPassword(String plainPassword) {
+		this.plainPassword = plainPassword;
+	}
+
+	private String pwd;
+
+	@Transient
+	public String getPwd() {
+		return pwd;
+	}
+
+	public void setPwd(String pwd) {
+		this.pwd = pwd;
+	}
+	
+	private String roleId;
+	
+	private String findPwdUrl="";
+	@Transient
+	public String getFindPwdUrl() {
+		return findPwdUrl;
+	}
+
+	public void setFindPwdUrl(String findPwdUrl) {
+		this.findPwdUrl = findPwdUrl;
+	}
+	
+	
+	
+
+}

+ 185 - 0
src/main/java/com/key/common/base/service/AccountManager.java

@@ -0,0 +1,185 @@
+package com.key.common.base.service;
+
+import java.util.List;
+
+import com.key.common.base.entity.User;
+import com.key.common.plugs.page.PageRequest;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.key.common.base.dao.UserDao;
+import com.key.common.exception.ServiceException;
+import com.key.common.plugs.page.Page;
+import com.key.common.plugs.page.PropertyFilter;
+import com.key.common.plugs.security.ShiroDbRealm;
+import com.key.common.utils.security.DigestUtils;
+
+/**
+ * 
+ * @author KeYuan
+ * @date 2013下午10:22:04
+ *
+ */
+@Service
+public class AccountManager {
+	private static Logger logger = LoggerFactory.getLogger(AccountManager.class);
+
+	@Autowired
+	private UserDao userDao;
+	
+
+//	@Autowired
+//	private NotifyMessageProducer notifyMessageProducer;//JMS消息推送
+	
+	private ShiroDbRealm shiroRealm;
+
+	/**
+	 * 在保存用户时,发送用户修改通知消息, 由消息接收者异步进行较为耗时的通知邮件发送.
+	 * 
+	 * 如果企图修改超级用户,取出当前操作员用户,打印其信息然后抛出异常.
+	 * 
+	 */
+	// 演示指定非默认名称的TransactionManager.
+	@Transactional
+	public void saveUser(User user) {
+		if (isSupervisor(user)) {
+			logger.warn("操作员{}尝试修改超级管理员用户", SecurityUtils.getSubject()
+					.getPrincipal());
+			throw new ServiceException("不能修改超级管理员用户");
+		}
+		//判断是否有重复用户
+		String shaPassword = DigestUtils.sha1Hex(user.getPlainPassword());
+//		System.out.println(shaPassword+":"+user.getPlainPassword());
+		user.setShaPassword(shaPassword);
+		boolean bool=user.getId()==null?true:false;
+		userDao.save(user);
+		if (shiroRealm != null) {
+			shiroRealm.clearCachedAuthorizationInfo(user.getLoginName());
+		}
+		/*if(bool){
+//			Email email=new Email();
+//			sendNotifyMessage(email);	使用jms辅助 发送邮件
+			System.out.println("新注册,发激活账号邮件");
+			simpleMailService.sendRegisterMailByAsync(user);
+		}*/
+	}
+
+	@Transactional
+	public void saveUp(User user){
+		if (isSupervisor(user)) {
+			logger.warn("操作员{}尝试修改超级管理员用户", SecurityUtils.getSubject().getPrincipal());
+			throw new ServiceException("不能修改超级管理员用户");
+		}
+		userDao.save(user);
+	}
+	
+	/*public User getByUid(String userSource,String uid){
+		Criterion cri1=Restrictions.eq("thirdSource", userSource);
+		Criterion cri2=Restrictions.eq("thirdUid", uid);
+		return userDao.findUnique(cri1,cri2);
+	}*/
+	//新注册用户,注册后
+//	private void sendNotifyMessage(Email email) {
+//		notifyMessageProducer.sendQueue(email);
+//	}
+
+	/**
+	 * 分页查询剧本,得到用户列表
+	 * @param page
+	 * @param filters
+	 * @return
+	 */
+	public Page<User> find(Page<User> page,List<PropertyFilter> filters){
+		return userDao.findPage(page, filters);
+	}
+
+	/**
+	 * 
+	 */
+	public Page<User> listUser(final PageRequest page, final List<PropertyFilter> filters){
+		Page<User> pageUser=userDao.findPage(page,filters);
+		return pageUser;
+	}
+	
+	/**
+	 * 判断是否超级管理员.
+	 */
+	private boolean isSupervisor(User user) {
+//		return (user.getId() != null && user.getId() == 1L);
+		return false;
+	}
+
+	@Transactional(readOnly = true)
+	public User getUser(String id) {
+		return userDao.get(id);
+	}
+	
+	/**
+	 * 使用属性过滤条件查询.
+	 */
+	@Transactional(readOnly = true)
+	public Page<User> searchUser(final PageRequest page, final List<PropertyFilter> filters) {
+		return userDao.findPage(page, filters);
+	}
+
+	
+	@Transactional(readOnly = true)
+	public User findUserByLoginName(String loginName) {
+		return userDao.findUniqueBy("loginName", loginName);
+	}
+	
+	@Transactional(readOnly = true)
+	public User findUserByLoginNameOrEmail(String loginName) {
+		if(loginName!=null){
+			if(loginName.contains("@")){
+				//是邮箱账号
+				return userDao.findUniqueBy("email", loginName);
+			}else{
+				return userDao.findUniqueBy("loginName", loginName);	
+			}
+		}
+		return null;
+	}
+	
+	/*验证邮箱是否存在*/
+	@Transactional(readOnly = true)
+	public User findUserByEmail(String email){
+		List<User> users=userDao.findBy("email", email);
+		if(users!=null && users.size()>0){
+			return users.get(0);
+		}
+		return null;
+	}
+
+	/**
+	 * 检查用户名是否唯一.
+	 *
+	 * @return loginName在数据库中唯一或等于oldLoginName时返回true.
+	 */
+	@Transactional(readOnly = true)
+	public boolean isLoginNameUnique(String newLoginName, String oldLoginName) {
+		return userDao.isPropertyUnique("loginName", newLoginName, oldLoginName);
+	}
+	
+	/**
+	 * 取出当前登陆用户
+	 */
+	public User getCurUser(){
+		Subject subject=SecurityUtils.getSubject();
+		
+		if(subject!=null){
+			Object principal=subject.getPrincipal();
+			if(principal!=null){
+				User user = findUserByLoginName(principal.toString());
+				return user;
+			}
+		}
+		return null;
+	}
+
+}

+ 14 - 0
src/main/java/com/key/common/dao/BaseDao.java

@@ -0,0 +1,14 @@
+package com.key.common.dao;
+
+import java.io.Serializable;
+
+
+/**
+ * @author keyuan(keyuan258@gmail.com)
+ *
+ * https://github.com/wkeyuan/DWSurvey
+ * http://dwsurvey.net
+ */
+public interface BaseDao<T,ID extends Serializable> extends IHibernateDao<T, ID>{
+	
+}

+ 14 - 0
src/main/java/com/key/common/dao/BaseDaoImpl.java

@@ -0,0 +1,14 @@
+package com.key.common.dao;
+
+import java.io.Serializable;
+
+/**
+ * @author keyuan(keyuan258@gmail.com)
+ *
+ * https://github.com/wkeyuan/DWSurvey
+ * http://dwsurvey.net
+ */
+public class BaseDaoImpl<T,ID extends Serializable> extends HibernateDao<T, ID> implements BaseDao<T, ID>{
+
+	
+}

+ 531 - 0
src/main/java/com/key/common/dao/HibernateDao.java

@@ -0,0 +1,531 @@
+/**
+ * Copyright (c) 2005-2011 springside.org.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 
+ * $Id: HibernateDao.java 1547 2011-05-05 14:43:07Z calvinxiu $
+ */
+package com.key.common.dao;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.key.common.plugs.page.PageRequest;
+import org.hibernate.Criteria;
+import org.hibernate.Query;
+import org.hibernate.criterion.CriteriaSpecification;
+import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Disjunction;
+import org.hibernate.criterion.MatchMode;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projection;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.impl.CriteriaImpl;
+import org.hibernate.transform.ResultTransformer;
+
+import com.key.common.plugs.page.Page;
+import com.key.common.plugs.page.PropertyFilter;
+import com.key.common.plugs.page.PropertyFilter.MatchType;
+import com.key.common.utils.AssertUtils;
+import com.key.common.utils.ReflectionUtils;
+
+/**
+ * 封装SpringSide扩展功能的Hibernat DAO泛型基类.
+ * 
+ * 扩展功能包括分页查询,按属性过滤条件列表查询.
+ * 
+ * @param <T> DAO操作的对象类型
+ * @param <ID> 主键类型
+ *
+ */
+
+public class HibernateDao<T, ID extends Serializable> extends SimpleHibernateDao<T, ID> implements IHibernateDao<T, ID> {
+
+	/**
+	 * 通过子类的泛型定义取得对象类型Class.
+	 * eg.
+	 * public class UserDao extends HibernateDao<User, Long>{
+	 * }
+	 */
+	public HibernateDao() {
+		super();
+		System.out.println("null super");
+	}
+
+	public HibernateDao(Class<T> entityClass) {
+		super(entityClass);
+		System.out.println(entityClass.getName());
+	}
+
+	//-- 分页查询函数 --//
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#getAll(com.key.common.orm.PageRequest)
+	 */
+	@Override
+	public Page<T> getAll(final PageRequest pageRequest) {
+		return findPage(pageRequest);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#findPage(com.key.common.orm.PageRequest, java.lang.String, java.lang.Object)
+	 */
+	@Override
+	public Page<T> findPage(final PageRequest pageRequest, String hql, final Object... values) {
+		AssertUtils.notNull(pageRequest, "pageRequest不能为空");
+
+		Page<T> page = new Page<T>(pageRequest);
+
+		if (pageRequest.isCountTotal()) {
+			long totalCount = countHqlResult(hql, values);
+			page.setTotalItems(totalCount);
+		}
+
+		if (pageRequest.isOrderBySetted()) {
+			hql = setOrderParameterToHql(hql, pageRequest);
+		}
+		Query q = createQuery(hql, values);
+
+		setPageParameterToQuery(q, pageRequest);
+
+		List result = q.list();
+		page.setResult(result);
+		return page;
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#findPage(com.key.common.orm.PageRequest, java.lang.String)
+	 */
+	@Override
+	public Page<T> findPage(final PageRequest pageRequest, String hql) {
+		AssertUtils.notNull(pageRequest, "pageRequest不能为空");
+		Page<T> page = new Page<T>(pageRequest);
+		if (pageRequest.isCountTotal()) {
+			long totalCount = countHqlResult(hql);
+			page.setTotalItems(totalCount);
+		}
+		if (pageRequest.isOrderBySetted()) {
+			hql = setOrderParameterToHql(hql, pageRequest);
+		}
+		Query q = createQuery(hql);
+		setPageParameterToQuery(q, pageRequest);
+		List result = q.list();
+		page.setResult(result);
+		return page;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#findPage(com.key.common.orm.PageRequest, java.lang.String, java.util.Map)
+	 */
+	@Override
+	public Page<T> findPage(final PageRequest pageRequest, String hql, final Map<String, ?> values) {
+		AssertUtils.notNull(pageRequest, "page不能为空");
+
+		Page<T> page = new Page<T>(pageRequest);
+
+		if (pageRequest.isCountTotal()) {
+			long totalCount = countHqlResult(hql, values);
+			page.setTotalItems(totalCount);
+		}
+
+		if (pageRequest.isOrderBySetted()) {
+			hql = setOrderParameterToHql(hql, pageRequest);
+		}
+
+		Query q = createQuery(hql, values);
+		setPageParameterToQuery(q, pageRequest);
+
+		List result = q.list();
+		page.setResult(result);
+		return page;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#findPage(com.key.common.orm.PageRequest, org.hibernate.criterion.Criterion)
+	 */
+	@Override
+	public Page<T> findPage(final PageRequest pageRequest, final Criterion... criterions) {
+		AssertUtils.notNull(pageRequest, "page不能为空");
+
+		Page<T> page = new Page<T>(pageRequest);
+
+		Criteria c = createCriteria(criterions);
+		System.out.println("pageRequest.isCountTotal():"+pageRequest.isCountTotal());
+		if (pageRequest.isCountTotal()) {
+			long totalCount = countCriteriaResult(c);
+			System.out.println("totalCount:"+totalCount);
+			page.setTotalItems(totalCount);
+			pageRequest.setTotalPage(page.getTotalPage());
+		}
+		if(pageRequest.isIslastpage()){
+			pageRequest.setPageNo(pageRequest.getTotalPage());
+			page.setPageNo(pageRequest.getPageNo());
+		}
+		setPageRequestToCriteria(c, pageRequest);
+
+		List result = c.list();
+		page.setResult(result);
+		return page;
+	}
+
+	/**
+	 * 在HQL的后面添加分页参数定义的orderBy, 辅助函数.
+	 */
+	protected String setOrderParameterToHql(final String hql, final PageRequest pageRequest) {
+		StringBuilder builder = new StringBuilder(hql);
+		builder.append(" order by");
+
+		for (PageRequest.Sort orderBy : pageRequest.getSort()) {
+			builder.append(String.format(" %s.%s %s,", DEFAULT_ALIAS, orderBy.getProperty(), orderBy.getDir()));
+		}
+
+		builder.deleteCharAt(builder.length() - 1);
+
+		return builder.toString();
+	}
+
+	/**
+	 * 设置分页参数到Query对象,辅助函数.
+	 */
+	protected Query setPageParameterToQuery(final Query q, final PageRequest pageRequest) {
+		q.setFirstResult(pageRequest.getOffset());
+		q.setMaxResults(pageRequest.getPageSize());
+		return q;
+	}
+
+	/**
+	 * 设置分页参数到Criteria对象,辅助函数.
+	 */
+	protected Criteria setPageRequestToCriteria(final Criteria c, final PageRequest pageRequest) {
+		AssertUtils.isTrue(pageRequest.getPageSize() > 0, "Page Size must larger than zero");
+		
+		c.setFirstResult(pageRequest.getOffset());
+		c.setMaxResults(pageRequest.getPageSize());
+
+		if (pageRequest.isOrderBySetted()) {
+			for (PageRequest.Sort sort : pageRequest.getSort()) {
+				if (PageRequest.Sort.ASC.equals(sort.getDir())) {
+					c.addOrder(Order.asc(sort.getProperty()));
+				} else {
+					c.addOrder(Order.desc(sort.getProperty()));
+				}
+			}
+		}
+		return c;
+	}
+
+	/**
+	 * 执行count查询获得本次Hql查询所能获得的对象总数.
+	 * 
+	 * 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询.
+	 */
+	protected long countHqlResult(final String hql, final Object... values) {
+		String countHql = prepareCountHql(hql);
+
+		try {
+			Long count = findUnique(countHql, values);
+			return count;
+		} catch (Exception e) {
+			throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e);
+		}
+	}
+
+	/**
+	 * 执行count查询获得本次Hql查询所能获得的对象总数.
+	 * 
+	 * 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询.
+	 */
+	protected long countHqlResult(final String hql, final Map<String, ?> values) {
+		String countHql = prepareCountHql(hql);
+
+		try {
+			Long count = findUnique(countHql, values);
+			return count;
+		} catch (Exception e) {
+			throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e);
+		}
+	}
+
+	private String prepareCountHql(String orgHql) {
+		String countHql = "select count (*) " + removeSelect(removeOrders(orgHql));
+		return countHql;
+	}
+
+	private static String removeSelect(String hql) {
+		int beginPos = hql.toLowerCase().indexOf("from");
+		return hql.substring(beginPos);
+	}
+
+	private static String removeOrders(String hql) {
+		Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
+		Matcher m = p.matcher(hql);
+		StringBuffer sb = new StringBuffer();
+		while (m.find()) {
+			m.appendReplacement(sb, "");
+		}
+		m.appendTail(sb);
+		return sb.toString();
+	}
+
+	/**
+	 * 执行count查询获得本次Criteria查询所能获得的对象总数.
+	 */
+	protected long countCriteriaResult(final Criteria c) {
+		CriteriaImpl impl = (CriteriaImpl) c;
+
+		// 先把Projection、ResultTransformer、OrderBy取出来,清空三者后再执行Count操作
+		Projection projection = impl.getProjection();
+		ResultTransformer transformer = impl.getResultTransformer();
+		System.out.println("count 查询"+impl.getEntityOrClassName());
+		List<CriteriaImpl.OrderEntry> orderEntries = null;
+		try {
+			orderEntries = (List) ReflectionUtils.getFieldValue(impl, "orderEntries");
+			ReflectionUtils.setFieldValue(impl, "orderEntries", new ArrayList());
+		} catch (Exception e) {
+			logger.error("不可能抛出的异常:{}", e.getMessage());
+		}
+		// 执行Count查询
+		
+		Long totalCountObject = (Long) c.setProjection(Projections.rowCount()).uniqueResult();
+		long totalCount = (totalCountObject != null) ? totalCountObject : 0;
+
+		// 将之前的Projection,ResultTransformer和OrderBy条件重新设回去
+		c.setProjection(projection);
+
+		if (projection == null) {
+			c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
+		}
+		if (transformer != null) {
+			c.setResultTransformer(transformer);
+		}
+		try {
+			ReflectionUtils.setFieldValue(impl, "orderEntries", orderEntries);
+		} catch (Exception e) {
+			logger.error("不可能抛出的异常:{}", e.getMessage());
+		}
+
+		return totalCount;
+	}
+
+	//-- 属性过滤条件(PropertyFilter)查询函数 --//
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#findBy(java.lang.String, java.lang.Object, com.key.common.orm.PropertyFilter.MatchType)
+	 */
+	@Override
+	public List<T> findBy(final String propertyName, final Object value, final MatchType matchType) {
+		Criterion criterion = buildCriterion(propertyName, value, matchType);
+		return find(criterion);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#find(java.util.List)
+	 */
+	@Override
+	public List<T> find(List<PropertyFilter> filters) {
+		Criterion[] criterions = buildCriterionByPropertyFilter(filters);
+		return find(criterions);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#findPage(com.key.common.orm.PageRequest, java.util.List)
+	 */
+	@Override
+	public Page<T> findPage(final PageRequest pageRequest, final List<PropertyFilter> filters) {
+		Criterion[] criterions = buildCriterionByPropertyFilter(filters);
+		System.out.println("findpage filters");
+		return findPage(pageRequest, criterions);
+	}
+
+	/**
+	 * 按属性条件参数创建Criterion,辅助函数.
+	 */
+	protected Criterion buildCriterion(final String propertyName, final Object propertyValue, final MatchType matchType) {
+		AssertUtils.hasText(propertyName, "propertyName不能为空");
+		Criterion criterion = null;
+		//根据MatchType构造criterion
+		switch (matchType) {
+		case EQ:
+			criterion = Restrictions.eq(propertyName, propertyValue);
+			break;
+		case LIKE:
+			criterion = Restrictions.like(propertyName, (String) propertyValue, MatchMode.ANYWHERE);
+			break;
+
+		case LE:
+			criterion = Restrictions.le(propertyName, propertyValue);
+			break;
+		case LT:
+			criterion = Restrictions.lt(propertyName, propertyValue);
+			break;
+		case GE:
+			criterion = Restrictions.ge(propertyName, propertyValue);
+			break;
+		case GT:
+			criterion = Restrictions.gt(propertyName, propertyValue);
+			break;
+		case NE:
+			criterion = Restrictions.ne(propertyName, propertyValue);
+		}
+		return criterion;
+	}
+
+	/**
+	 * 按属性条件列表创建Criterion数组,辅助函数.
+	 */
+	protected Criterion[] buildCriterionByPropertyFilter(final List<PropertyFilter> filters) {
+		List<Criterion> criterionList = new ArrayList<Criterion>();
+		for (PropertyFilter filter : filters) {
+			if (!filter.hasMultiProperties()) { //只有一个属性需要比较的情况.
+				Criterion criterion = buildCriterion(filter.getPropertyName(), filter.getMatchValue(),
+						filter.getMatchType());
+				criterionList.add(criterion);
+			} else {//包含多个属性需要比较的情况,进行or处理.
+				Disjunction disjunction = Restrictions.disjunction();
+				for (String param : filter.getPropertyNames()) {
+					Criterion criterion = buildCriterion(param, filter.getMatchValue(), filter.getMatchType());
+					disjunction.add(criterion);
+				}
+				criterionList.add(disjunction);
+			}
+		}
+		return criterionList.toArray(new Criterion[criterionList.size()]);
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.IHibernateDao#findAll(com.key.common.orm.PageRequest, java.util.List)
+	 */
+	@Override
+	public List<T> findAll(final PageRequest pageRequest, final List<PropertyFilter> filters) {
+		Criterion[] criterions = buildCriterionByPropertyFilter(filters);
+		Criteria c = createCriteria(criterions);
+		if (pageRequest.isOrderBySetted()) {
+			for (PageRequest.Sort sort : pageRequest.getSort()) {
+				if (PageRequest.Sort.ASC.equals(sort.getDir())) {
+					c.addOrder(Order.asc(sort.getProperty()));
+				} else {
+					c.addOrder(Order.desc(sort.getProperty()));
+				}
+			}
+		}
+		return c.list();
+	}
+	
+	@Override
+	public T getModel(ID id) {
+		T t = null;
+		try {
+			if (id != null && !"".equals(id)) {
+				t = get(id);
+			}
+			if (t == null) {
+				t = entityClass.newInstance();
+			}
+		} catch (InstantiationException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IllegalAccessException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return t;
+	}
+
+	@Override
+	public List<T> find(String orderByProperty, boolean isAsc,
+			Criterion... criterions) {
+		Criteria c = createCriteria(criterions);
+		if (isAsc) {
+			c.addOrder(Order.asc(orderByProperty));
+		} else {
+			c.addOrder(Order.desc(orderByProperty));
+		}
+		return c.list();
+	}
+	
+	@Override
+	public T findFirst(String orderByProperty, boolean isAsc,
+			Criterion... criterions) {
+		Criteria c = createCriteria(criterions);
+		if (isAsc) {
+			c.addOrder(Order.asc(orderByProperty));
+		} else {
+			c.addOrder(Order.desc(orderByProperty));
+		}
+		c.setMaxResults(1);
+		return (T) c.uniqueResult();
+	}
+	
+	@Override
+	public T findFirst(String orderByProperty, boolean isAsc,
+			List<Criterion> criterions) {
+		Criteria c = createCriteria(criterions);
+		if (isAsc) {
+			c.addOrder(Order.asc(orderByProperty));
+		} else {
+			c.addOrder(Order.desc(orderByProperty));
+		}
+		c.setMaxResults(1);
+		return (T) c.uniqueResult();
+	}
+
+	@Override
+	public Object findUniObjs(String hql,Object... values ) {
+		Query q = createQuery(hql, values);
+		return q.uniqueResult();
+	}
+
+	@Override
+	public List<Object[]> findList(String hql, Object... values) {
+		Query q = createQuery(hql, values);
+		return q.list();
+	}
+
+	@Override
+	public T findFirst(Criterion... criterions) {
+		Criteria c = createCriteria(criterions);
+		c.setMaxResults(1);
+		return (T) c.uniqueResult();
+	}
+	
+	public T findFirst(List<Criterion> criterions) {
+		Criteria c = createCriteria(criterions);
+		c.setMaxResults(1);
+		return (T) c.uniqueResult();
+	}
+	
+	@Override
+	public Page<T> findPageList(PageRequest pageRequest,
+			List<Criterion> criterions) {
+		if(criterions!=null && criterions.size()>0){
+			Criteria c = createCriteria(criterions);
+			return findPageCriteria(pageRequest, c);
+		}
+		return findPage(pageRequest);
+	}
+	
+	public Page<T> findPageCriteria(PageRequest pageRequest,Criteria c){
+		Page<T> page = new Page<T>(pageRequest);
+		if (pageRequest.isCountTotal()) {
+			long totalCount = countCriteriaResult(c);
+			System.out.println("totalCount:"+totalCount);
+			page.setTotalItems(totalCount);
+			pageRequest.setTotalPage(page.getTotalPage());
+		}
+		if(pageRequest.isIslastpage()){
+			pageRequest.setPageNo(pageRequest.getTotalPage());
+			page.setPageNo(pageRequest.getPageNo());
+		}
+		setPageRequestToCriteria(c, pageRequest);
+
+		List result = c.list();
+		page.setResult(result);
+		return page;
+	}
+	
+}

+ 135 - 0
src/main/java/com/key/common/dao/IHibernateDao.java

@@ -0,0 +1,135 @@
+package com.key.common.dao;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import com.key.common.plugs.page.Page;
+import com.key.common.plugs.page.PageRequest;
+import org.hibernate.Criteria;
+import org.hibernate.criterion.Criterion;
+
+import com.key.common.plugs.page.PropertyFilter;
+import com.key.common.plugs.page.PropertyFilter.MatchType;
+
+public interface IHibernateDao<T, ID extends Serializable> extends ISimpleHibernateDao<T, ID> {
+
+	public static final String DEFAULT_ALIAS = "x";
+
+	/**
+	 * 分页获取全部对象.
+	 */
+	public abstract Page<T> getAll(final PageRequest pageRequest);
+
+	/**
+	 * 按HQL分页查询.
+	 * 
+	 * @param pageRequest 分页参数.
+	 * @param hql hql语句.
+	 * @param values 数量可变的查询参数,按顺序绑定.
+	 * 
+	 * @return 分页查询结果, 附带结果列表及所有查询输入参数.
+	 */
+	public abstract Page<T> findPage(final PageRequest pageRequest, String hql,
+			final Object... values);
+
+	/**
+	 * 按HQL分页查询.
+	 * 
+	 * @param pageRequest 分页参数.
+	 * @param hql hql语句.
+	 * 
+	 * @return 分页查询结果, 附带结果列表及所有查询输入参数.
+	 */
+	public abstract Page<T> findPage(final PageRequest pageRequest, String hql);
+
+	/**
+	 * 按HQL分页查询.
+	 * 
+	 * @param page 分页参数.
+	 * @param hql hql语句.
+	 * @param values 命名参数,按名称绑定.
+	 * 
+	 * @return 分页查询结果, 附带结果列表及所有查询输入参数.
+	 */
+	public abstract Page<T> findPage(final PageRequest pageRequest, String hql,
+			final Map<String, ?> values);
+
+	/**
+	 * 按Criteria分页查询.
+	 * 
+	 * @param page 分页参数.
+	 * @param criterions 数量可变的Criterion.
+	 * 
+	 * @return 分页查询结果.附带结果列表及所有查询输入参数.
+	 */
+	public abstract Page<T> findPage(final PageRequest pageRequest,
+			final Criterion... criterions);
+
+	public abstract Page<T> findPageList(final PageRequest pageRequest,
+			final List<Criterion> criterions);
+	
+	public Page<T> findPageCriteria(PageRequest pageRequest,Criteria c);
+	/**
+	 * 按属性查找对象列表,支持多种匹配方式.
+	 * 
+	 * @param matchType 匹配方式,目前支持的取值见PropertyFilter的MatcheType enum.
+	 */
+	public abstract List<T> findBy(final String propertyName,
+			final Object value, final MatchType matchType);
+
+	/**
+	 * 按属性过滤条件列表查找对象列表.
+	 */
+	public abstract List<T> find(List<PropertyFilter> filters);
+
+	/**
+	 * 按属性过滤条件列表分页查找对象.
+	 */
+	public abstract Page<T> findPage(final PageRequest pageRequest,
+			final List<PropertyFilter> filters);
+
+	/**
+	 * 查询所有记录不分页,支持排序
+	 * @param pageRequest
+	 * @param filters
+	 * @return
+	 */
+	public abstract List<T> findAll(final PageRequest pageRequest,
+			final List<PropertyFilter> filters);
+	
+	/**
+	 * action转入id得到模型
+	 * @param id
+	 * @return
+	 */
+	public T getModel(ID id);
+	
+	/**
+	 * 排序--取出一列数据
+	 */
+	public  List<T>  find(String orderByProperty,boolean isAsc,Criterion... criterions);
+	
+	/**
+	 * 取出第一条
+	 */
+	public  T  findFirst(Criterion... criterions);
+	public  T  findFirst(List<Criterion> criterions);
+	public  T  findFirst(String orderByProperty,boolean isAsc,Criterion... criterions);
+	public  T  findFirst(String orderByProperty, boolean isAsc,List<Criterion> criterions); 
+	
+	/**
+	 * 执行一条hql返回 一个object[]
+	 * 
+	 */
+	public Object findUniObjs(String hql,Object... values );
+	
+	/**
+	 * 返回list<Object[]>
+	 * @param hql
+	 * @param values
+	 * @return
+	 */
+	public List<Object[]> findList(String hql,Object... values );
+	
+}

+ 213 - 0
src/main/java/com/key/common/dao/ISimpleHibernateDao.java

@@ -0,0 +1,213 @@
+package com.key.common.dao;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.hibernate.Criteria;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.Criterion;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public interface ISimpleHibernateDao<T, ID extends Serializable> {
+
+	/**
+	 * 取得sessionFactory.
+	 */
+	public abstract SessionFactory getSessionFactory();
+
+	/**
+	 * 采用@Autowired按类型注入SessionFactory, 当有多个SesionFactory的时候在子类重载本函数.
+	 */
+	@Autowired
+	public abstract void setSessionFactory(final SessionFactory sessionFactory);
+
+	/**
+	 * 取得当前Session.
+	 */
+	public abstract Session getSession();
+
+	/**
+	 * 保存新增或修改的对象.
+	 */
+	public abstract void save(final T entity);
+
+	/**
+	 * 删除对象.
+	 * 
+	 * @param entity 对象必须是session中的对象或含id属性的transient对象.
+	 */
+	public abstract void delete(final T entity);
+
+	/**
+	 * 按id删除对象.
+	 */
+	public abstract void delete(final ID id);
+
+	/**
+	 * 按id获取对象.
+	 */
+	public abstract T get(final ID id);
+
+	/**
+	 * 按id列表获取对象列表.
+	 */
+	public abstract List<T> get(final Collection<ID> ids);
+
+	/**
+	 *	获取全部对象.
+	 */
+	public abstract List<T> getAll();
+
+	/**
+	 *	获取全部对象, 支持按属性行序.
+	 */
+	public abstract List<T> getAll(String orderByProperty, boolean isAsc);
+
+	/**
+	 * 按属性查找对象列表, 匹配方式为相等.
+	 */
+	public abstract List<T> findBy(final String propertyName, final Object value);
+
+	/**
+	 * 按属性查找唯一对象, 匹配方式为相等.
+	 */
+	public abstract T findUniqueBy(final String propertyName, final Object value);
+
+	/**
+	 * 按HQL查询对象列表.
+	 * 
+	 * @param values 数量可变的参数,按顺序绑定.
+	 */
+	public abstract <X> List<X> find(final String hql, final Object... values);
+
+	/**
+	 * 按HQL查询对象列表.
+	 * 
+	 * @param values 命名参数,按名称绑定.
+	 */
+	public abstract <X> List<X> find(final String hql,
+			final Map<String, ?> values);
+
+	/**
+	 * 按HQL查询唯一对象.
+	 * 
+	 * @param values 数量可变的参数,按顺序绑定.
+	 */
+	public abstract <X> X findUnique(final String hql, final Object... values);
+
+	/**
+	 * 按HQL查询唯一对象.
+	 * 
+	 * @param values 命名参数,按名称绑定.
+	 */
+	public abstract <X> X findUnique(final String hql,
+			final Map<String, ?> values);
+
+	/**
+	 * 执行HQL进行批量修改/删除操作.
+	 * 
+	 * @param values 数量可变的参数,按顺序绑定.
+	 * @return 更新记录数.
+	 */
+	public abstract int batchExecute(final String hql, final Object... values);
+
+	/**
+	 * 执行HQL进行批量修改/删除操作.
+	 * 
+	 * @param values 命名参数,按名称绑定.
+	 * @return 更新记录数.
+	 */
+	public abstract int batchExecute(final String hql,
+			final Map<String, ?> values);
+
+	/**
+	 * 根据查询HQL与参数列表创建Query对象.
+	 * 与find()函数可进行更加灵活的操作.
+	 * 
+	 * @param values 数量可变的参数,按顺序绑定.
+	 */
+	public abstract Query createQuery(final String queryString,
+			final Object... values);
+
+	/**
+	 * 根据查询HQL与参数列表创建Query对象.
+	 * 与find()函数可进行更加灵活的操作.
+	 * 
+	 * @param values 命名参数,按名称绑定.
+	 */
+	public abstract Query createQuery(final String queryString,
+			final Map<String, ?> values);
+
+	/**
+	 * 按Criteria查询对象列表.
+	 * 
+	 * @param criterions 数量可变的Criterion.
+	 */
+	public abstract List<T> find(final Criterion... criterions);
+
+	/**
+	 * 按Criteria查询唯一对象.
+	 * 
+	 * @param criterions 数量可变的Criterion.
+	 */
+	public abstract T findUnique(final Criterion... criterions);
+
+	/**
+	 * 根据Criterion条件创建Criteria.
+	 * 与find()函数可进行更加灵活的操作.
+	 * 
+	 * @param criterions 数量可变的Criterion.
+	 */
+	public abstract Criteria createCriteria(final Criterion... criterions);
+	
+	/**
+	 * @param criterions
+	 * @return
+	 */
+	public Criteria createCriteria(List<Criterion> criterions);
+
+	/**
+	 * 初始化对象.
+	 * 使用load()方法得到的仅是对象Proxy, 在传到View层前需要进行初始化.
+	 * 如果传入entity, 则只初始化entity的直接属性,但不会初始化延迟加载的关联集合和属性.
+	 * 如需初始化关联属性,需执行:
+	 * Hibernate.initialize(user.getRoles()),初始化User的直接属性和关联集合.
+	 * Hibernate.initialize(user.getDescription()),初始化User的直接属性和延迟加载的Description属性.
+	 */
+	public abstract void initProxyObject(Object proxy);
+
+	/**
+	 * Flush当前Session.
+	 */
+	public abstract void flush();
+
+	/**
+	 * 为Query添加distinct transformer.
+	 * 预加载关联对象的HQL会引起主对象重复, 需要进行distinct处理.
+	 */
+	public abstract Query distinct(Query query);
+
+	/**
+	 * 为Criteria添加distinct transformer.
+	 * 预加载关联对象的HQL会引起主对象重复, 需要进行distinct处理.
+	 */
+	public abstract Criteria distinct(Criteria criteria);
+
+	/**
+	 * 取得对象的主键名.
+	 */
+	public abstract String getIdName();
+
+	/**
+	 * 判断对象的属性值在数据库内是否唯一.
+	 * 
+	 * 在修改对象的情景下,如果属性新修改的值(value)等于属性原来的值(orgValue)则不作比较.
+	 */
+	public abstract boolean isPropertyUnique(final String propertyName,
+			final Object newValue, final Object oldValue);
+
+}

+ 349 - 0
src/main/java/com/key/common/dao/SimpleHibernateDao.java

@@ -0,0 +1,349 @@
+/**
+ * Copyright (c) 2005-2011 springside.org.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 
+ * $Id: SimpleHibernateDao.java 1594 2011-05-11 14:22:29Z calvinxiu $
+ */
+package com.key.common.dao;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import com.key.common.utils.AssertUtils;
+import com.key.common.utils.ReflectionUtils;
+import org.hibernate.Criteria;
+import org.hibernate.Hibernate;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.CriteriaSpecification;
+import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.metadata.ClassMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 封装Hibernate原生API的DAO泛型基类.
+ * 
+ * 参考Spring2.5自带的Petlinc例子, 取消了HibernateTemplate, 直接使用Hibernate原生API.
+ * 
+ * @param <T> DAO操作的对象类型
+ * @param <ID> 主键类型
+ *
+ */
+public class SimpleHibernateDao<T, ID extends Serializable> implements ISimpleHibernateDao<T, ID> {
+
+	protected Logger logger = LoggerFactory.getLogger(getClass());
+
+	protected SessionFactory sessionFactory;
+
+	protected Class<T> entityClass;
+
+	/**
+	 * 通过子类的泛型定义取得对象类型Class.
+	 * eg.
+	 * public class UserDao extends SimpleHibernateDao<User, Long>
+	 */
+	public SimpleHibernateDao() {
+		this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass());
+	}
+
+	public SimpleHibernateDao(Class<T> entityClass) {
+		this.entityClass = entityClass;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#getSessionFactory()
+	 */
+	@Override
+	public SessionFactory getSessionFactory() {
+		return sessionFactory;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#setSessionFactory(org.hibernate.SessionFactory)
+	 */
+	@Override
+	@Autowired
+	public void setSessionFactory(final SessionFactory sessionFactory) {
+		this.sessionFactory = sessionFactory;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#getSession()
+	 */
+	@Override
+	public Session getSession() {
+		return sessionFactory.getCurrentSession();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#save(T)
+	 */
+	@Override
+	public void save(final T entity) {
+		try {
+			AssertUtils.notNull(entity, "entity不能为空");
+			getSession().saveOrUpdate(entity);
+			logger.debug("save entity: {}", entity);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#delete(T)
+	 */
+	@Override
+	public void delete(final T entity) {
+		AssertUtils.notNull(entity, "entity不能为空");
+		getSession().delete(entity);
+		logger.debug("delete entity: {}", entity);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#delete(ID)
+	 */
+	@Override
+	public void delete(final ID id) {
+		AssertUtils.notNull(id, "id不能为空");
+		delete(get(id));
+		logger.debug("delete entity {},id is {}", entityClass.getSimpleName(), id);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#get(ID)
+	 */
+	@Override
+	public T get(final ID id) {
+		AssertUtils.notNull(id, "id不能为空");
+		return (T) getSession().load(entityClass, id);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#get(java.util.Collection)
+	 */
+	@Override
+	public List<T> get(final Collection<ID> ids) {
+		return find(Restrictions.in(getIdName(), ids));
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#getAll()
+	 */
+	@Override
+	public List<T> getAll() {
+		return find();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#getAll(java.lang.String, boolean)
+	 */
+	@Override
+	public List<T> getAll(String orderByProperty, boolean isAsc) {
+		Criteria c = createCriteria();
+		if (isAsc) {
+			c.addOrder(Order.asc(orderByProperty));
+		} else {
+			c.addOrder(Order.desc(orderByProperty));
+		}
+		return c.list();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#findBy(java.lang.String, java.lang.Object)
+	 */
+	@Override
+	public List<T> findBy(final String propertyName, final Object value) {
+		AssertUtils.hasText(propertyName, "propertyName不能为空");
+		Criterion criterion = Restrictions.eq(propertyName, value);
+		return find(criterion);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#findUniqueBy(java.lang.String, java.lang.Object)
+	 */
+	@Override
+	public T findUniqueBy(final String propertyName, final Object value) {
+		AssertUtils.hasText(propertyName, "propertyName不能为空");
+		Criterion criterion = Restrictions.eq(propertyName, value);
+		return (T) createCriteria(criterion).uniqueResult();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#find(java.lang.String, java.lang.Object)
+	 */
+	@Override
+	public <X> List<X> find(final String hql, final Object... values) {
+		return createQuery(hql, values).list();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#find(java.lang.String, java.util.Map)
+	 */
+	@Override
+	public <X> List<X> find(final String hql, final Map<String, ?> values) {
+		return createQuery(hql, values).list();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#findUnique(java.lang.String, java.lang.Object)
+	 */
+	@Override
+	public <X> X findUnique(final String hql, final Object... values) {
+		return (X) createQuery(hql, values).uniqueResult();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#findUnique(java.lang.String, java.util.Map)
+	 */
+	@Override
+	public <X> X findUnique(final String hql, final Map<String, ?> values) {
+		return (X) createQuery(hql, values).uniqueResult();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#batchExecute(java.lang.String, java.lang.Object)
+	 */
+	@Override
+	public int batchExecute(final String hql, final Object... values) {
+		return createQuery(hql, values).executeUpdate();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#batchExecute(java.lang.String, java.util.Map)
+	 */
+	@Override
+	public int batchExecute(final String hql, final Map<String, ?> values) {
+		return createQuery(hql, values).executeUpdate();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#createQuery(java.lang.String, java.lang.Object)
+	 */
+	@Override
+	public Query createQuery(final String queryString, final Object... values) {
+		AssertUtils.hasText(queryString, "queryString不能为空");
+		Query query = getSession().createQuery(queryString);
+		if (values != null) {
+			for (int i = 0; i < values.length; i++) {
+				query.setParameter(i, values[i]);
+			}
+		}
+		return query;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#createQuery(java.lang.String, java.util.Map)
+	 */
+	@Override
+	public Query createQuery(final String queryString, final Map<String, ?> values) {
+		AssertUtils.hasText(queryString, "queryString不能为空");
+		Query query = getSession().createQuery(queryString);
+		if (values != null) {
+			query.setProperties(values);
+		}
+		return query;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#find(org.hibernate.criterion.Criterion)
+	 */
+	@Override
+	public List<T> find(final Criterion... criterions) {
+		return createCriteria(criterions).list();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#findUnique(org.hibernate.criterion.Criterion)
+	 */
+	@Override
+	public T findUnique(final Criterion... criterions) {
+		return (T) createCriteria(criterions).uniqueResult();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#createCriteria(org.hibernate.criterion.Criterion)
+	 */
+	@Override
+	public Criteria createCriteria(final Criterion... criterions) {
+		Criteria criteria = getSession().createCriteria(entityClass);
+		for (Criterion c : criterions) {
+			criteria.add(c);
+		}
+		return criteria;
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#createCriteria(org.hibernate.criterion.Criterion)
+	 */
+	@Override
+	public Criteria createCriteria(List<Criterion> criterions) {
+		Criteria criteria = getSession().createCriteria(entityClass);
+		for (Criterion c : criterions) {
+			criteria.add(c);
+		}
+		return criteria;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#initProxyObject(java.lang.Object)
+	 */
+	@Override
+	public void initProxyObject(Object proxy) {
+		Hibernate.initialize(proxy);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#flush()
+	 */
+	@Override
+	public void flush() {
+		getSession().flush();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#distinct(org.hibernate.Query)
+	 */
+	@Override
+	public Query distinct(Query query) {
+		query.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
+		return query;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#distinct(org.hibernate.Criteria)
+	 */
+	@Override
+	public Criteria distinct(Criteria criteria) {
+		criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
+		return criteria;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#getIdName()
+	 */
+	@Override
+	public String getIdName() {
+		ClassMetadata meta = getSessionFactory().getClassMetadata(entityClass);
+		return meta.getIdentifierPropertyName();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.key.common.orm.hibernate.ISimpleHibernateDao#isPropertyUnique(java.lang.String, java.lang.Object, java.lang.Object)
+	 */
+	@Override
+	public boolean isPropertyUnique(final String propertyName, final Object newValue, final Object oldValue) {
+		if (newValue == null || newValue.equals(oldValue)) {
+			return true;
+		}
+		Object object = findUniqueBy(propertyName, newValue);
+		return (object == null);
+	}
+}

+ 29 - 0
src/main/java/com/key/common/exception/ServiceException.java

@@ -0,0 +1,29 @@
+package com.key.common.exception;
+
+/**
+ * Service层公用的Exception.
+ * 
+ * 继承自RuntimeException, 从由Spring管理事务的函数中抛出时会触发事务回滚.
+ * 
+ * @author keyuan
+ */
+public class ServiceException extends RuntimeException {
+
+	private static final long serialVersionUID = 1401593546385403720L;
+
+	public ServiceException() {
+		super();
+	}
+
+	public ServiceException(String message) {
+		super(message);
+	}
+
+	public ServiceException(Throwable cause) {
+		super(cause);
+	}
+
+	public ServiceException(String message, Throwable cause) {
+		super(message, cause);
+	}
+}

+ 161 - 0
src/main/java/com/key/common/plugs/aliyun/AliyunOSS.java

@@ -0,0 +1,161 @@
+package com.key.common.plugs.aliyun;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import com.aliyun.oss.OSSClient;
+import com.aliyun.oss.model.ListObjectsRequest;
+import com.aliyun.oss.model.OSSObject;
+import com.aliyun.oss.model.OSSObjectSummary;
+import com.aliyun.oss.model.ObjectListing;
+import com.aliyun.oss.model.ObjectMetadata;
+import com.aliyun.oss.model.PutObjectResult;
+import com.key.common.utils.DiaowenProperty;
+import org.apache.struts2.dispatcher.multipart.UploadedFile;
+
+/**
+ * @author keyuan(keyuan258@gmail.com)
+ *
+ * https://github.com/wkeyuan/DWSurvey
+ * http://dwsurvey.net
+ */
+public class AliyunOSS {
+
+	/*
+	static String ACCESS_KEY_ID = "";
+	static String SECRET_ACCESS_KEY = "";
+	// 以杭州为例
+	//static String endpoint = "http://oss-cn-shenzhen-internal.aliyuncs.com";
+	static String ENDPOINT = "http://gz.bcebos.com";
+	
+	public static String  WENJUANHTML_BACKET="";
+	public static String  UPLOADFILE_BACKET="";
+	public static String  UPLOADFILE_JM_BACKET="";
+	*/
+	
+	private static OSSClient getOSSClient() {
+//		OSSClient client = new OSSClient(ENDPOINT, ACCESS_KEY_ID,SECRET_ACCESS_KEY);
+		OSSClient client = new OSSClient(DiaowenProperty.ENDPOINT, DiaowenProperty.ACCESS_KEY_ID,
+				DiaowenProperty.SECRET_ACCESS_KEY);
+		return client;
+	}
+
+	public static void putObject(String bucketName, File file, String fileName)
+			throws IOException {
+
+		// 初始化OSSClient
+		OSSClient client = getOSSClient();
+
+		// 获取指定文件的输入流
+		// File file = new File(fileRealPath + fileName);
+		InputStream content = new FileInputStream(file);
+
+		// 创建上传Object的Metadata
+		ObjectMetadata meta = new ObjectMetadata();
+
+		// 必须设置ContentLength
+		// meta.setContentLength(file.length());
+		meta.setContentEncoding("UTF-8");
+		// 上传Object.
+		String key = fileName;
+		PutObjectResult result = client.putObject(bucketName, key, content,
+				meta);
+		System.out.println(key);
+		// 打印ETag
+		System.out.println(result.getETag());
+		content.close();
+	}
+
+	public static void putObject(String bucketName, InputStream inputStream,
+			String fileName) throws FileNotFoundException {
+
+		// 初始化OSSClient
+		OSSClient client = getOSSClient();
+
+		// 获取指定文件的输入流
+		// File file = new File(fileRealPath + fileName);
+		// InputStream content = new FileInputStream(file);
+		InputStream content = inputStream;
+
+		// 创建上传Object的Metadata
+		ObjectMetadata meta = new ObjectMetadata();
+
+		// 必须设置ContentLength
+		// meta.setContentLength(file.length());
+		// meta.setContentEncoding("UTF-8");
+		// 上传Object.
+		String key = fileName;
+		PutObjectResult result = client.putObject(bucketName, key, content,
+				meta);
+		System.out.println(key);
+		// 打印ETag
+		System.out.println(result.getETag());
+	}
+
+	public static InputStream getObject(String bucketName, String fileName) {
+		// 初始化OSSClient
+		OSSClient client = getOSSClient();
+
+		// client.getObject(new GetObjectRequest(bucketName, key),new
+		// File(filename));
+		OSSObject ossObject = client.getObject(bucketName, fileName);
+		InputStream inputStream = ossObject.getObjectContent();
+
+		return inputStream;
+	}
+
+	public static List<OSSObjectSummary> getObjectList(String bucketName,
+			String prefix, int endIndex, int maxKeys) {
+		System.out.println(prefix);
+		// 初始化OSSClient
+		OSSClient client = getOSSClient();
+
+		// 构造ListObjectsRequest请求
+		ListObjectsRequest listObjectsRequest = new ListObjectsRequest(
+				bucketName);
+
+		// 递归列出fun目录下的所有文件
+		listObjectsRequest.setPrefix(prefix);
+		listObjectsRequest.setMaxKeys(maxKeys);
+		// listObjectsRequest.setMarker("ueditor/jsp/upload/image/20150614/1434267568217077840.jpg");
+
+		ObjectListing listing = null;
+		String nextMarker = null;
+
+		// endIndex>maxKeys
+		int pageNum = endIndex / maxKeys;
+		for (int i = 0; i < pageNum; i++) {
+			if (nextMarker != null) {
+				listObjectsRequest.setMarker(nextMarker);
+			}
+			listing = client.listObjects(listObjectsRequest);
+			nextMarker = listing.getNextMarker();
+		}
+
+		System.out.println("nextMarker:" + nextMarker);
+		// 遍历所有Object
+		List<OSSObjectSummary> objectSummarys = listing.getObjectSummaries();
+
+		return objectSummarys;
+		// 遍历所有CommonPrefix
+		/*
+		 * System.out.println("\nCommonPrefixs:"); for (String commonPrefix :
+		 * listing.getCommonPrefixes()) { System.out.println(commonPrefix); }
+		 */
+	}
+
+	public static void main(String[] args) {
+
+		List<OSSObjectSummary> objectSummaries = AliyunOSS.getObjectList(
+				DiaowenProperty.UPLOADFILE_BACKET, "ueditor/jsp/upload/image/", 4, 2);
+		System.out.println(objectSummaries.size());
+		for (OSSObjectSummary ossObjectSummary : objectSummaries) {
+			System.out.println(ossObjectSummary.getKey() + ":"
+					+ ossObjectSummary.getSize());
+		}
+	}
+}

+ 159 - 0
src/main/java/com/key/common/plugs/baiduyun/BaiduBOS.java

@@ -0,0 +1,159 @@
+package com.key.common.plugs.baiduyun;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import com.baidubce.auth.DefaultBceCredentials;
+import com.baidubce.services.bos.BosClient;
+import com.baidubce.services.bos.BosClientConfiguration;
+import com.baidubce.services.bos.model.BosObject;
+import com.baidubce.services.bos.model.BosObjectSummary;
+import com.baidubce.services.bos.model.ListObjectsRequest;
+import com.baidubce.services.bos.model.ListObjectsResponse;
+import com.baidubce.services.bos.model.ObjectMetadata;
+import com.baidubce.services.bos.model.PutObjectResponse;
+import com.key.common.utils.DiaowenProperty;
+
+/**
+ * @author keyuan(keyuan258@gmail.com)
+ *
+ * https://github.com/wkeyuan/DWSurvey
+ * http://dwsurvey.net
+ */
+public class BaiduBOS {	
+	/*
+	static String ACCESS_KEY_ID = "";
+	static String SECRET_ACCESS_KEY = "";
+	static String ENDPOINT = "http://gz.bcebos.com";
+	
+	public static String  WENJUANHTML_BACKET="";
+	public static String  UPLOADFILE_BACKET="";
+	public static String  UPLOADFILE_JM_BACKET="";
+	*/
+	
+	public static BosClient getClient(){
+		 // 初始化一个BosClient
+	    BosClientConfiguration config = new BosClientConfiguration();
+//	    config.setCredentials(new DefaultBceCredentials(ACCESS_KEY_ID,SECRET_ACCESS_KEY));
+//	    config.setEndpoint(ENDPOINT);
+	    config.setCredentials(new DefaultBceCredentials(DiaowenProperty.ACCESS_KEY_ID,DiaowenProperty.SECRET_ACCESS_KEY));
+	    config.setEndpoint(DiaowenProperty.ENDPOINT);
+	    BosClient client = new BosClient(config);
+	    return client;
+	}
+	
+	public static void putObject(String bucketName,File file,String fileName) throws IOException{
+	
+	    BosClient client = getClient();
+	    // 获取数据流
+	    InputStream content = new FileInputStream(file);
+		// 创建上传Object的Metadata
+		ObjectMetadata meta = new ObjectMetadata();
+		
+		// 必须设置ContentLength
+//		meta.setContentLength(file.length());
+//		meta.setContentEncoding("UTF-8");
+		
+		// 上传Object.
+		String objectKey=fileName;
+		PutObjectResponse result = client.putObject(bucketName, objectKey, content, meta);
+		System.out.println(objectKey);
+		// 打印ETag
+		System.out.println(result.getETag());
+		content.close();
+	}
+	
+	
+	public static void putObject(String bucketName,InputStream inputStream,String fileName) throws FileNotFoundException{
+	
+		// 初始化OSSClient
+		BosClient client = getClient();
+		// 获取指定文件的输入流
+	//	File file = new File(fileRealPath + fileName);
+	//	InputStream content = new FileInputStream(file);
+		InputStream content = inputStream;
+		
+		// 创建上传Object的Metadata
+		ObjectMetadata meta = new ObjectMetadata();
+		
+		// 必须设置ContentLength
+	//	meta.setContentLength(file.length());
+//		meta.setContentEncoding("UTF-8");
+		// 上传Object.
+		String key=fileName;
+		PutObjectResponse result = client.putObject(bucketName, key, content, meta);
+		System.out.println(key);
+		// 打印ETag
+		System.out.println(result.getETag());
+	}
+	
+	
+	public static InputStream getObject(String bucketName,String fileName){
+		// 初始化OSSClient
+		BosClient client = getClient();
+		//client.getObject(new GetObjectRequest(bucketName, key),new File(filename));
+		BosObject bosObject=client.getObject(bucketName, fileName);
+		
+		InputStream inputStream=bosObject.getObjectContent();
+		
+		 // 获取Object,返回结果为BosObject对象
+		return inputStream;
+	}
+	
+	
+	public static List<BosObjectSummary> getObjectList(String bucketName,String prefix,int endIndex,int maxKeys){
+		
+
+		System.out.println(prefix);
+		// 初始化OSSClient
+		BosClient client = getClient();
+
+		// 构造ListObjectsRequest请求
+		ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
+
+		// 递归列出目录下的所有文件
+		listObjectsRequest.setPrefix(prefix);
+		listObjectsRequest.setMaxKeys(maxKeys);
+
+		
+		
+		// listObjectsRequest.setMarker("ueditor/jsp/upload/image/20150614/1434267568217077840.jpg");
+
+		ListObjectsResponse listing = null;
+		String nextMarker = null;
+
+		// endIndex>maxKeys
+		int pageNum = endIndex / maxKeys;
+		for (int i = 0; i < pageNum; i++) {
+			if (nextMarker != null) {
+				listObjectsRequest.setMarker(nextMarker);
+			}
+			listing = client.listObjects(listObjectsRequest);
+			nextMarker = listing.getNextMarker();
+		}
+
+		System.out.println("nextMarker:" + nextMarker);
+		// 遍历所有Object
+		List<BosObjectSummary> objectSummarys = listing.getContents();
+		
+		return objectSummarys;
+		// 遍历所有CommonPrefix
+		/*
+		 * System.out.println("\nCommonPrefixs:"); for (String commonPrefix :
+		 * listing.getCommonPrefixes()) { System.out.println(commonPrefix); }
+		 */
+	}
+	
+	
+	public static void main(String[] args) {
+		
+//		 BaiduBOS.getObjectList(BaiduBOS.UPLOADFILE_BACKET, "ueditor/jsp/upload/image/",4,2);
+		 
+		BaiduBOS.getObject(DiaowenProperty.WENJUANHTML_BACKET, "index.html");
+	}
+}
+

+ 59 - 0
src/main/java/com/key/common/plugs/data/mysql/MySQLDatabaseBackup.java

@@ -0,0 +1,59 @@
+package com.key.common.plugs.data.mysql;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * MySQL数据库备份
+ * 
+ * @author GaoHuanjie
+ */
+public class MySQLDatabaseBackup {
+
+	/**
+	 * Java代码实现MySQL数据库导出
+	 * 
+	 * @author GaoHuanjie
+	 * @param hostIP MySQL数据库所在服务器地址IP
+	 * @param userName 进入数据库所需要的用户名
+	 * @param password 进入数据库所需要的密码
+	 * @param savePath 数据库导出文件保存路径
+	 * @param fileName 数据库导出文件文件名
+	 * @param databaseName 要导出的数据库名
+	 * @return 返回true表示导出成功,否则返回false。
+	 */
+	public static boolean exportDatabaseTool(String hostIP, String userName, String password, String savePath, String fileName,	String databaseName) {
+		File saveFile = new File(savePath);
+		if (!saveFile.exists()) {// 如果目录不存在
+			saveFile.mkdirs();// 创建文件夹
+		}
+		if (!savePath.endsWith(File.separator)) {
+			savePath = savePath + File.separator;
+		}
+
+		StringBuilder stringBuilder = new StringBuilder();
+		stringBuilder.append("mysqldump").append(" --opt").append(" -h").append(hostIP);
+		stringBuilder.append(" --user=").append(userName) .append(" --password=").append(password).append(" --lock-all-tables=true");
+		stringBuilder.append(" --result-file=").append(savePath + fileName).append(" --default-character-set=utf8 ").append(databaseName);
+		try {
+			System.out.println(stringBuilder.toString());
+			Process process = Runtime.getRuntime().exec(stringBuilder.toString());
+			if (process.waitFor() == 0) {// 0 表示线程正常终止。
+				return true;
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+		return false;
+	}
+
+	public static void main(String[] args) throws InterruptedException {
+		if (exportDatabaseTool("localhost", "root", "", "/Users/keyuan/Documents/", "2016.sql", "test")) {
+			System.out.println("数据库备份成功!!!");
+		} else {
+			System.out.println("数据库备份失败!!!");
+		}
+	}
+}

+ 79 - 0
src/main/java/com/key/common/plugs/email/Email.java

@@ -0,0 +1,79 @@
+package com.key.common.plugs.email;
+
+public class Email {
+	private String to;// 收件人
+	private String subject;// 主题
+	private String username;// 用户称呼
+	private String content;// 内容
+	private String date;// 日期
+	private String sendEmailId;
+
+	public Email() {
+		super();
+	}
+
+	public Email(String to, String subject, String username, String content,
+			String date) {
+		super();
+		this.to = to;
+		this.subject = subject;
+		this.username = username;
+		this.content = content;
+		this.date = date;
+	}
+
+	public String getUsername() {
+		return username;
+	}
+
+	public void setUsername(String username) {
+		this.username = username;
+	}
+
+	public String getTo() {
+		return to;
+	}
+
+	public void setTo(String to) {
+		this.to = to;
+	}
+
+	public String getSubject() {
+		return subject;
+	}
+
+	public void setSubject(String subject) {
+		this.subject = subject;
+	}
+
+	public String getContent() {
+		return content;
+	}
+
+	public void setContent(String content) {
+		this.content = content;
+	}
+
+	public String getDate() {
+		return date;
+	}
+
+	public void setDate(String date) {
+		this.date = date;
+	}
+
+	public String getSendEmailId() {
+		return sendEmailId;
+	}
+
+	public void setSendEmailId(String sendEmailId) {
+		this.sendEmailId = sendEmailId;
+	}
+
+	@Override
+	public String toString() {
+		return "Email [content=" + content + ", date=" + date + ", subject="
+				+ subject + ", to=" + to + ", username=" + username + "]";
+	}
+
+}

+ 16 - 0
src/main/java/com/key/common/plugs/email/MailService.java

@@ -0,0 +1,16 @@
+package com.key.common.plugs.email;
+
+import com.key.common.base.entity.User;
+
+public interface MailService {
+    
+    //发送邮件
+    public boolean sendMail(String to,String title,String content);
+    //发送注册激活邮件
+    public boolean sendRegisterMailByAsync(User user);
+    //发送找回密码邮件
+    public boolean sendFindPwdMailByAsync(User user);
+    //发送邀请邮件
+    public String sendSurveyInviteMail(final String dwSubject,final String substitutionVars);
+    
+}

+ 70 - 0
src/main/java/com/key/common/plugs/freemarker/FreeMarkertUtil.java

@@ -0,0 +1,70 @@
+package com.key.common.plugs.freemarker;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import freemarker.template.Configuration;
+import freemarker.template.DefaultObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+
+/**
+ * @author ajun
+ * @http://blog.csdn.net/ajun_studio
+ **/
+public class FreeMarkertUtil {
+
+	private static Configuration config = new Configuration();
+
+	/**
+	 * @param templateName
+	 *            模板名字
+	 * @param root
+	 *            模板根 用于在模板内输出结果集
+	 * @param out
+	 *            输出对象 具体输出到哪里
+	 */
+	public static void processTemplate(String templateName, Map<?, ?> root,
+			Writer out) {
+		try {
+			// 获得模板
+			Template template = config.getTemplate(templateName, "utf-8");
+			// 生成文件(这里是我们是生成html)
+			template.process(root, out);
+			out.flush();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (TemplateException e) {
+			e.printStackTrace();
+		} finally {
+			try {
+				out.close();
+				out = null;
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	/**
+	 * 初始化模板配置
+	 * 
+	 * @param servletContext
+	 *            javax.servlet.ServletContext
+	 * @param templateDir
+	 *            模板位置
+	 */
+	public static void initConfig(ServletContext servletContext,
+			String templateDir) {
+		config.setLocale(Locale.CHINA);
+		config.setDefaultEncoding("utf-8");
+		config.setEncoding(Locale.CHINA, "utf-8");
+		templateDir="WEB-INF/templates";
+		config.setServletContextForTemplateLoading(servletContext, templateDir);
+		config.setObjectWrapper(new DefaultObjectWrapper());
+	}
+}

+ 26 - 0
src/main/java/com/key/common/plugs/freemarker/FreemarkerTest.java

@@ -0,0 +1,26 @@
+package com.key.common.plugs.freemarker;
+
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.jsp.PageContext;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+
+public class FreemarkerTest {
+	public void execute(PageContext pageContext) throws Exception {
+		Configuration cfg = new Configuration();
+		cfg.setServletContextForTemplateLoading(pageContext.getServletContext(), "WEB-INF/templates");
+
+		Map root = new HashMap();
+		root.put("name", "Tom");
+
+		Template t = cfg.getTemplate("test.ftl");
+
+		Writer out = pageContext.getResponse().getWriter();
+
+		t.process(root, out);
+	}
+}

+ 14 - 0
src/main/java/com/key/common/plugs/ipaddr/IPEntry.java

@@ -0,0 +1,14 @@
+package com.key.common.plugs.ipaddr;
+
+public class IPEntry {
+    public String beginIp;
+    public String endIp;
+    public String country;
+    public String area;
+    public IPEntry() {
+        beginIp = endIp = country = area = "";
+    }
+    public String toString() {
+        return this.area + "  " + this.country + "IP范围:" + this.beginIp + "-" + this.endIp;
+    }
+}

+ 661 - 0
src/main/java/com/key/common/plugs/ipaddr/IPSeeker.java

@@ -0,0 +1,661 @@
+package com.key.common.plugs.ipaddr;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteOrder;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class IPSeeker {
+	private class IPLocation {
+		public String country;
+		public String area;
+
+		public IPLocation() {
+			country = area = "";
+		}
+
+		public IPLocation getCopy() {
+			IPLocation ret = new IPLocation();
+			ret.country = country;
+			ret.area = area;
+			return ret;
+		}
+	}
+
+	private static final String IP_FILE = IPSeeker.class.getResource(
+			"qqwry.dat").toString().substring(5);
+	// 一些固定常量,比如记录长度等等
+	private static final int IP_RECORD_LENGTH = 7;
+	private static final byte AREA_FOLLOWED = 0x01;
+	private static final byte NO_AREA = 0x2;
+	// 用来做为cache,查询一个ip时首先查看cache,以减少不必要的重复查找
+	private Hashtable ipCache;
+	// 随机文件访问类
+	private RandomAccessFile ipFile;
+	// 内存映射文件
+	private MappedByteBuffer mbb;
+	// 单一模式实例
+	private static IPSeeker instance = new IPSeeker();
+	// 起始地区的开始和结束的绝对偏移
+	private long ipBegin, ipEnd;
+	// 为提高效率而采用的临时变量
+	private IPLocation loc;
+	private byte[] buf;
+	private byte[] b4;
+	private byte[] b3;
+
+	/**
+	 * 私有构造函数
+	 */
+	private IPSeeker() {
+		ipCache = new Hashtable();
+		loc = new IPLocation();
+		buf = new byte[100];
+		b4 = new byte[4];
+		b3 = new byte[3];
+		try {
+			ipFile = new RandomAccessFile(IP_FILE, "r");
+		} catch (FileNotFoundException e) {
+			System.out.println(IPSeeker.class.getResource("qqwry.dat")
+					.toString());
+			System.out.println(IP_FILE);
+			System.out.println("IP地址信息文件没有找到,IP显示功能将无法使用");
+			ipFile = null;
+		}
+		// 如果打开文件成功,读取文件头信息
+		if (ipFile != null) {
+			try {
+				ipBegin = readLong4(0);
+				ipEnd = readLong4(4);
+				if (ipBegin == -1 || ipEnd == -1) {
+					ipFile.close();
+					ipFile = null;
+				}
+			} catch (IOException e) {
+				System.out.println("IP地址信息文件格式有错误,IP显示功能将无法使用");
+				ipFile = null;
+			}
+		}
+	}
+
+	/**
+	 * @return 单一实例
+	 */
+	public static IPSeeker getInstance() {
+		return instance;
+	}
+
+	/**
+	 * 给定一个地点的不完全名字,得到一系列包含s子串的IP范围记录
+	 * 
+	 * @param s
+	 *            地点子串
+	 * @return 包含IPEntry类型的List
+	 */
+	public List getIPEntriesDebug(String s) {
+		List ret = new ArrayList();
+		long endOffset = ipEnd + 4;
+		for (long offset = ipBegin + 4; offset <= endOffset; offset += IP_RECORD_LENGTH) {
+			// 读取结束IP偏移
+			long temp = readLong3(offset);
+			// 如果temp不等于-1,读取IP的地点信息
+			if (temp != -1) {
+				IPLocation loc = getIPLocation(temp);
+				// 判断是否这个地点里面包含了s子串,如果包含了,添加这个记录到List中,如果没有,继续
+				if (loc.country.indexOf(s) != -1 || loc.area.indexOf(s) != -1) {
+					IPEntry entry = new IPEntry();
+					entry.country = loc.country;
+					entry.area = loc.area;
+					// 得到起始IP
+					readIP(offset - 4, b4);
+					entry.beginIp = Utils.getIpStringFromBytes(b4);
+					// 得到结束IP
+					readIP(temp, b4);
+					entry.endIp = Utils.getIpStringFromBytes(b4);
+					// 添加该记录
+					ret.add(entry);
+				}
+			}
+		}
+		return ret;
+	}
+
+	public List getIPEntries(String s) {
+		List ret = new ArrayList();
+		try {
+			// 映射IP信息文件到内存中
+			if (mbb == null) {
+				FileChannel fc = ipFile.getChannel();
+				mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, ipFile.length());
+				mbb.order(ByteOrder.LITTLE_ENDIAN);
+			}
+			int endOffset = (int) ipEnd;
+			for (int offset = (int) ipBegin + 4; offset <= endOffset; offset += IP_RECORD_LENGTH) {
+				int temp = readInt3(offset);
+				if (temp != -1) {
+					IPLocation loc = getIPLocation(temp);
+					// 判断是否这个地点里面包含了s子串,如果包含了,添加这个记录到List中,如果没有,继续
+					if (loc.country.indexOf(s) != -1
+							|| loc.area.indexOf(s) != -1) {
+						IPEntry entry = new IPEntry();
+						entry.country = loc.country;
+						entry.area = loc.area;
+						// 得到起始IP
+						readIP(offset - 4, b4);
+						entry.beginIp = Utils.getIpStringFromBytes(b4);
+						// 得到结束IP
+						readIP(temp, b4);
+						entry.endIp = Utils.getIpStringFromBytes(b4);
+						// 添加该记录
+						ret.add(entry);
+					}
+				}
+			}
+		} catch (IOException e) {
+			System.out.println(e.getMessage());
+		}
+		return ret;
+	}
+
+	private int readInt3(int offset) {
+		mbb.position(offset);
+		return mbb.getInt() & 0x00FFFFFF;
+	}
+
+	/**
+	 * 从内存映射文件的当前位置开始的3个字节读取一个int
+	 * 
+	 * @return
+	 */
+	private int readInt3() {
+		return mbb.getInt() & 0x00FFFFFF;
+	}
+
+	/**
+	 * 根据IP得到国家名
+	 * 
+	 * @param ip
+	 *            ip的字节数组形式
+	 * @return 国家名字符串
+	 */
+	public String getCountry(byte[] ip) {
+		// 检查ip地址文件是否正常
+		if (ipFile == null)
+			return "错误的IP数据库文件";
+		// 保存ip,转换ip字节数组为字符串形式
+		String ipStr = Utils.getIpStringFromBytes(ip);
+		// 先检查cache中是否已经包含有这个ip的结果,没有再搜索文件
+		if (ipCache.containsKey(ipStr)) {
+			IPLocation loc = (IPLocation) ipCache.get(ipStr);
+			return loc.country;
+		} else {
+			IPLocation loc = getIPLocation(ip);
+			ipCache.put(ipStr, loc.getCopy());
+			return loc.country;
+		}
+	}
+
+	/**
+	 * 根据IP得到国家名
+	 * 
+	 * @param ip
+	 *            IP的字符串形式
+	 * @return 国家名字符串
+	 */
+	public String getCountry(String ip) {
+		return getCountry(Utils.getIpByteArrayFromString(ip));
+	}
+
+	/**
+	 * 根据IP得到地区名
+	 * 
+	 * @param ip
+	 *            ip的字节数组形式
+	 * @return 地区名字符串
+	 */
+	public String getArea(byte[] ip) {
+		// 检查ip地址文件是否正常
+		if (ipFile == null)
+			return "错误的IP数据库文件";
+		// 保存ip,转换ip字节数组为字符串形式
+		String ipStr = Utils.getIpStringFromBytes(ip);
+		// 先检查cache中是否已经包含有这个ip的结果,没有再搜索文件
+		if (ipCache.containsKey(ipStr)) {
+			IPLocation loc = (IPLocation) ipCache.get(ipStr);
+			return loc.area;
+		} else {
+			IPLocation loc = getIPLocation(ip);
+			ipCache.put(ipStr, loc.getCopy());
+			return loc.area;
+		}
+	}
+
+	/**
+	 * 根据IP得到地区名
+	 * 
+	 * @param ip
+	 *            IP的字符串形式
+	 * @return 地区名字符串
+	 */
+	public String getArea(String ip) {
+		return getArea(Utils.getIpByteArrayFromString(ip));
+	}
+
+	/**
+	 * 根据ip搜索ip信息文件,得到IPLocation结构,所搜索的ip参数从类成员ip中得到
+	 * 
+	 * @param ip
+	 *            要查询的IP
+	 * @return IPLocation结构
+	 */
+	private IPLocation getIPLocation(byte[] ip) {
+		IPLocation info = null;
+		long offset = locateIP(ip);
+		if (offset != -1)
+			info = getIPLocation(offset);
+		if (info == null) {
+			info = new IPLocation();
+			info.country = "未知国家";
+			info.area = "未知地区";
+		}
+		return info;
+	}
+
+	/**
+	 * 从offset位置读取4个字节为一个long,因为java为big-endian格式,所以没办法 用了这么一个函数来做转换
+	 * 
+	 * @param offset
+	 * @return 读取的long值,返回-1表示读取文件失败
+	 */
+	private long readLong4(long offset) {
+		long ret = 0;
+		try {
+			ipFile.seek(offset);
+			ret |= (ipFile.readByte() & 0xFF);
+			ret |= ((ipFile.readByte() << 8) & 0xFF00);
+			ret |= ((ipFile.readByte() << 16) & 0xFF0000);
+			ret |= ((ipFile.readByte() << 24) & 0xFF000000);
+			return ret;
+		} catch (IOException e) {
+			return -1;
+		}
+	}
+
+	/**
+	 * 从offset位置读取3个字节为一个long,因为java为big-endian格式,所以没办法 用了这么一个函数来做转换
+	 * 
+	 * @param offset
+	 * @return 读取的long值,返回-1表示读取文件失败
+	 */
+	private long readLong3(long offset) {
+		long ret = 0;
+		try {
+			ipFile.seek(offset);
+			ipFile.readFully(b3);
+			ret |= (b3[0] & 0xFF);
+			ret |= ((b3[1] << 8) & 0xFF00);
+			ret |= ((b3[2] << 16) & 0xFF0000);
+			return ret;
+		} catch (IOException e) {
+			return -1;
+		}
+	}
+
+	/**
+	 * 从当前位置读取3个字节转换成long
+	 * 
+	 * @return
+	 */
+	private long readLong3() {
+		long ret = 0;
+		try {
+			ipFile.readFully(b3);
+			ret |= (b3[0] & 0xFF);
+			ret |= ((b3[1] << 8) & 0xFF00);
+			ret |= ((b3[2] << 16) & 0xFF0000);
+			return ret;
+		} catch (IOException e) {
+			return -1;
+		}
+	}
+
+	/**
+	 * 从offset位置读取四个字节的ip地址放入ip数组中,读取后的ip为big-endian格式,但是
+	 * 文件中是little-endian形式,将会进行转换
+	 * 
+	 * @param offset
+	 * @param ip
+	 */
+	private void readIP(long offset, byte[] ip) {
+		try {
+			ipFile.seek(offset);
+			ipFile.readFully(ip);
+			byte temp = ip[0];
+			ip[0] = ip[3];
+			ip[3] = temp;
+			temp = ip[1];
+			ip[1] = ip[2];
+			ip[2] = temp;
+		} catch (IOException e) {
+			System.out.println(e.getMessage());
+		}
+	}
+
+	/**
+	 * 从offset位置读取四个字节的ip地址放入ip数组中,读取后的ip为big-endian格式,但是
+	 * 文件中是little-endian形式,将会进行转换
+	 * 
+	 * @param offset
+	 * @param ip
+	 */
+	private void readIP(int offset, byte[] ip) {
+		mbb.position(offset);
+		mbb.get(ip);
+		byte temp = ip[0];
+		ip[0] = ip[3];
+		ip[3] = temp;
+		temp = ip[1];
+		ip[1] = ip[2];
+		ip[2] = temp;
+	}
+
+	/**
+	 * 把类成员ip和beginIp比较,注意这个beginIp是big-endian的
+	 * 
+	 * @param ip
+	 *            要查询的IP
+	 * @param beginIp
+	 *            和被查询IP相比较的IP
+	 * @return 相等返回0,ip大于beginIp则返回1,小于返回-1。
+	 */
+	private int compareIP(byte[] ip, byte[] beginIp) {
+		for (int i = 0; i < 4; i++) {
+			int r = compareByte(ip[i], beginIp[i]);
+			if (r != 0)
+				return r;
+		}
+		return 0;
+	}
+
+	/**
+	 * 把两个byte当作无符号数进行比较
+	 * 
+	 * @param b1
+	 * @param b2
+	 * @return 若b1大于b2则返回1,相等返回0,小于返回-1
+	 */
+	private int compareByte(byte b1, byte b2) {
+		if ((b1 & 0xFF) > (b2 & 0xFF)) // 比较是否大于
+			return 1;
+		else if ((b1 ^ b2) == 0)// 判断是否相等
+			return 0;
+		else
+			return -1;
+	}
+
+	/**
+	 * 这个方法将根据ip的内容,定位到包含这个ip国家地区的记录处,返回一个绝对偏移 方法使用二分法查找。
+	 * 
+	 * @param ip
+	 *            要查询的IP
+	 * @return 如果找到了,返回结束IP的偏移,如果没有找到,返回-1
+	 */
+	private long locateIP(byte[] ip) {
+		long m = 0;
+		int r;
+		// 比较第一个ip项
+		readIP(ipBegin, b4);
+		r = compareIP(ip, b4);
+		if (r == 0)
+			return ipBegin;
+		else if (r < 0)
+			return -1;
+		// 开始二分搜索
+		for (long i = ipBegin, j = ipEnd; i < j;) {
+			m = getMiddleOffset(i, j);
+			readIP(m, b4);
+			r = compareIP(ip, b4);
+			// log.debug(Utils.getIpStringFromBytes(b));
+			if (r > 0)
+				i = m;
+			else if (r < 0) {
+				if (m == j) {
+					j -= IP_RECORD_LENGTH;
+					m = j;
+				} else
+					j = m;
+			} else
+				return readLong3(m + 4);
+		}
+		// 如果循环结束了,那么i和j必定是相等的,这个记录为最可能的记录,但是并非
+		// 肯定就是,还要检查一下,如果是,就返回结束地址区的绝对偏移
+		m = readLong3(m + 4);
+		readIP(m, b4);
+		r = compareIP(ip, b4);
+		if (r <= 0)
+			return m;
+		else
+			return -1;
+	}
+
+	/**
+	 * 得到begin偏移和end偏移中间位置记录的偏移
+	 * 
+	 * @param begin
+	 * @param end
+	 * @return
+	 */
+	private long getMiddleOffset(long begin, long end) {
+		long records = (end - begin) / IP_RECORD_LENGTH;
+		records >>= 1;
+		if (records == 0)
+			records = 1;
+		return begin + records * IP_RECORD_LENGTH;
+	}
+
+	/**
+	 * 给定一个ip国家地区记录的偏移,返回一个IPLocation结构
+	 * 
+	 * @param offset
+	 * @return
+	 */
+	private IPLocation getIPLocation(long offset) {
+		try {
+			// 跳过4字节ip
+			ipFile.seek(offset + 4);
+			// 读取第一个字节判断是否标志字节
+			byte b = ipFile.readByte();
+			if (b == AREA_FOLLOWED) {
+				// 读取国家偏移
+				long countryOffset = readLong3();
+				// 跳转至偏移处
+				ipFile.seek(countryOffset);
+				// 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向
+				b = ipFile.readByte();
+				if (b == NO_AREA) {
+					loc.country = readString(readLong3());
+					ipFile.seek(countryOffset + 4);
+				} else
+					loc.country = readString(countryOffset);
+				// 读取地区标志
+				loc.area = readArea(ipFile.getFilePointer());
+			} else if (b == NO_AREA) {
+				loc.country = readString(readLong3());
+				loc.area = readArea(offset + 8);
+			} else {
+				loc.country = readString(ipFile.getFilePointer() - 1);
+				loc.area = readArea(ipFile.getFilePointer());
+			}
+			return loc;
+		} catch (IOException e) {
+			return null;
+		}
+	}
+
+	/**
+	 * @param offset
+	 * @return
+	 */
+	private IPLocation getIPLocation(int offset) {
+		// 跳过4字节ip
+		mbb.position(offset + 4);
+		// 读取第一个字节判断是否标志字节
+		byte b = mbb.get();
+		if (b == AREA_FOLLOWED) {
+			// 读取国家偏移
+			int countryOffset = readInt3();
+			// 跳转至偏移处
+			mbb.position(countryOffset);
+			// 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向
+			b = mbb.get();
+			if (b == NO_AREA) {
+				loc.country = readString(readInt3());
+				mbb.position(countryOffset + 4);
+			} else
+				loc.country = readString(countryOffset);
+			// 读取地区标志
+			loc.area = readArea(mbb.position());
+		} else if (b == NO_AREA) {
+			loc.country = readString(readInt3());
+			loc.area = readArea(offset + 8);
+		} else {
+			loc.country = readString(mbb.position() - 1);
+			loc.area = readArea(mbb.position());
+		}
+		return loc;
+	}
+
+	/**
+	 * 从offset偏移开始解析后面的字节,读出一个地区名
+	 * 
+	 * @param offset
+	 * @return 地区名字符串
+	 * @throws IOException
+	 */
+	private String readArea(long offset) throws IOException {
+		ipFile.seek(offset);
+		byte b = ipFile.readByte();
+		if (b == 0x01 || b == 0x02) {
+			long areaOffset = readLong3(offset + 1);
+			if (areaOffset == 0)
+				return "未知地区";
+			else
+				return readString(areaOffset);
+		} else
+			return readString(offset);
+	}
+
+	/**
+	 * @param offset
+	 * @return
+	 */
+	private String readArea(int offset) {
+		mbb.position(offset);
+		byte b = mbb.get();
+		if (b == 0x01 || b == 0x02) {
+			int areaOffset = readInt3();
+			if (areaOffset == 0)
+				return "未知地区";
+			else
+				return readString(areaOffset);
+		} else
+			return readString(offset);
+	}
+
+	/**
+	 * 从offset偏移处读取一个以0结束的字符串
+	 * 
+	 * @param offset
+	 * @return 读取的字符串,出错返回空字符串
+	 */
+	private String readString(long offset) {
+		try {
+			ipFile.seek(offset);
+			int i;
+			for (i = 0, buf[i] = ipFile.readByte(); buf[i] != 0; buf[++i] = ipFile
+					.readByte())
+				;
+			if (i != 0)
+				return Utils.getString(buf, 0, i, "GBK");
+		} catch (IOException e) {
+			System.out.println(e.getMessage());
+		}
+		return "";
+	}
+
+	/**
+	 * 从内存映射文件的offset位置得到一个0结尾字符串
+	 * 
+	 * @param offset
+	 * @return
+	 */
+	private String readString(int offset) {
+		try {
+			mbb.position(offset);
+			int i;
+			for (i = 0, buf[i] = mbb.get(); buf[i] != 0; buf[++i] = mbb.get())
+				;
+			if (i != 0)
+				return Utils.getString(buf, 0, i, "GBK");
+		} catch (IllegalArgumentException e) {
+			System.out.println(e.getMessage());
+		}
+		return "";
+	}
+
+	public String getAddress(String ip) {
+		String country = getCountry(ip).equals(" CZ88.NET") ? ""
+				: getCountry(ip);
+		String area = getArea(ip).equals(" CZ88.NET") ? "" : getArea(ip);
+		String address = country;// + " " + area;
+		// System.out.println("country:"+country+"  area:"+area);
+		return address.trim();
+	}
+
+	public static void main(String[] args) {
+		IPSeeker aa = new IPSeeker();
+		List<String> ips = new ArrayList<String>();
+		ips.add("198.41.0.4");
+		ips.add("192.228.79.201");
+		ips.add("192.33.4.12");
+		ips.add("128.8.10.90");
+		ips.add("192.203.230.10");
+		ips.add("192.5.5.241");
+		ips.add("192.112.36.4");
+		ips.add("128.63.2.53");
+		ips.add("192.36.148.17");
+		ips.add("192.58.128.30");
+		ips.add("193.0.14.129");
+		ips.add("199.7.83.42");
+		ips.add("202.12.27.33");
+		ips.add("123.114.32.60");
+		ips.add("114.249.204.13");
+		ips.add("0:0:0:0:0:0:0:1");
+		for (String string : ips) {
+			// 124.72.237.255  福建省福州市 电信
+			// 124.72.238.0    124.72.239.255  福建省福州市 (连江县)电信ADSL
+			
+			//省..市
+			//..市
+			//..省..
+			//..省
+			//清华大学=北京
+			//内蒙古..市
+			//内蒙古..
+			//广西..市
+			
+			System.out.println(string + "[" + aa.getAddress(string) + "]"+aa.getCountry(string));
+			
+			// System.out.println(string+"["+aa.getCountry(string)+"]");
+		}
+
+	}
+}

+ 129 - 0
src/main/java/com/key/common/plugs/ipaddr/IPService.java

@@ -0,0 +1,129 @@
+package com.key.common.plugs.ipaddr;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class IPService {
+	@Autowired
+	private IPSeeker ipSeeker;
+
+	public String getIp(HttpServletRequest request) {
+		
+		//Http Header:X-Forwarded-For
+		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.getRemoteAddr();
+		}
+//		ip=replaceIPv6LocalIp(ip);
+		ip=checkLocalIp(ip);
+		if(ip!=null && ip.indexOf(",")>0){
+			ip=ip.substring(0,ip.indexOf(","));
+		}
+		return ip;
+	}
+
+	/**
+	 * 检查以localhost,127.0.0.1访问时得到真实IP
+	 * @param ip
+	 * @return
+	 */
+	public String checkLocalIp(String ip){
+		if("0:0:0:0:0:0:0:1".equals(ip) || "127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1%0".equals(ip)){
+			 try {
+					InetAddress inetAddress = InetAddress.getLocalHost();
+					ip=inetAddress.getHostAddress();
+					
+					 if(ip!=null && ip.length()>15){ //"***.***.***.***".length() = 15
+				         if(ip.indexOf(",")>0){
+				        	 ip = ip.substring(0,ip.indexOf(","));
+				         }
+				     }
+					 System.out.println(ip);
+			} catch (UnknownHostException e) {
+//				e.printStackTrace();
+			}
+		}
+		return ip;
+	}
+	
+	public String replaceIPv6LocalIp(String ip){
+		if("0:0:0:0:0:0:0:1".equals(ip)){
+			ip="127.0.0.1";
+		}
+		return ip;
+	}
+	
+	public String getCountry(String ip) {
+		if(ip==null){
+			return "";
+		}
+		return ipSeeker.getCountry(ip);
+	}
+
+	/**
+	 * 根据IP,查出此ip所在的城市
+	 * 
+	 * @param ip
+	 * @return
+	 */
+	public String getCurCity(String ip) {
+		String city = ipSeeker.getCountry(ip);
+		city = city.replaceAll("\\S+省|市.*|[内蒙古|广西]", "");
+		city = city.replaceAll("清华大学.*", "北京");
+		return city;
+	}
+
+	/**
+	 * 根据 getCountry(ip);得到的地址得到城市
+	 * 
+	 * @param country
+	 * @return
+	 */
+	public String getCurCityByCountry(String country) {
+		// 省..市
+		// ..市
+		// ..省..市..
+		// ..省..
+		// ..省
+		// 清华大学=北京
+		// 内蒙古..市
+		// 内蒙古..
+		// 广西..市
+		String city = country;
+		city = city.replaceAll("\\S+省|市.*|[内蒙古|广西]", "");
+		city = city.replaceAll("清华大学.*", "北京");
+		return city;
+	}
+
+	/**
+	 * 根据 request对象得到数据请求者所在的城市
+	 * 
+	 * @param request
+	 * @return
+	 */
+	public String getCurCity(HttpServletRequest request) {
+		String ip = getIp(request);
+		// ip="202.106.46.151";
+		String city = ipSeeker.getCountry(ip);
+		city = city.replaceAll("\\S+省|市.*|[内蒙古|广西]", "");
+		city = city.replaceAll("清华大学.*", "北京");
+		return city;
+	}
+	
+	public static void main(String[] args) {
+		String ip="111.206.20.59, 123.151.42.46, 121.42.17.215,";
+		System.out.println(ip.substring(0,ip.indexOf(",")));
+	}
+}

+ 18 - 0
src/main/java/com/key/common/plugs/ipaddr/NsLookup.java

@@ -0,0 +1,18 @@
+package com.key.common.plugs.ipaddr;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+public class NsLookup {
+
+	public static void main(String[] args) {
+		String name="www.sun.com";
+		try {
+			InetAddress address = InetAddress.getByName(name);
+			System.out.println(name + " : " + address.getHostAddress());
+		}catch (UnknownHostException uhe) {
+			System.err.println("Unable to find: " + name);
+		}
+	}
+}

+ 100 - 0
src/main/java/com/key/common/plugs/ipaddr/Utils.java

@@ -0,0 +1,100 @@
+package com.key.common.plugs.ipaddr;
+
+import java.io.UnsupportedEncodingException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ */
+public class Utils {
+	
+	@Autowired
+	private IPSeeker ipSeeker;
+	
+    /**
+     * 从ip的字符串形式得到字节数组形式
+     * @param ip 字符串形式的ip
+     * @return 字节数组形式的ip
+     */
+    public static byte[] getIpByteArrayFromString(String ip) {
+        byte[] ret = new byte[4];
+        java.util.StringTokenizer st = new java.util.StringTokenizer(ip, ".");
+        try {
+            ret[0] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);
+            ret[1] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);
+            ret[2] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);
+            ret[3] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
+        }
+        return ret;
+    }
+    
+    public static void main(String args[]){
+         byte[] a=getIpByteArrayFromString(args[0]);
+          for(int i=0;i< a.length;i++)
+                System.out.println(a[i]);
+          System.out.println(getIpStringFromBytes(a)); 
+    }
+    /**
+     * 对原始字符串进行编码转换,如果失败,返回原始的字符串
+     * @param s 原始字符串
+     * @param srcEncoding 源编码方式
+     * @param destEncoding 目标编码方式
+     * @return 转换编码后的字符串,失败返回原始字符串
+     */
+    public static String getString(String s, String srcEncoding, String destEncoding) {
+        try {
+            return new String(s.getBytes(srcEncoding), destEncoding);
+        } catch (UnsupportedEncodingException e) {
+            return s;
+        }
+    }
+    
+    /**
+     * 根据某种编码方式将字节数组转换成字符串
+     * @param b 字节数组
+     * @param encoding 编码方式
+     * @return 如果encoding不支持,返回一个缺省编码的字符串
+     */
+    public static String getString(byte[] b, String encoding) {
+        try {
+            return new String(b, encoding);
+        } catch (UnsupportedEncodingException e) {
+            return new String(b);
+        }
+    }
+    
+    /**
+     * 根据某种编码方式将字节数组转换成字符串
+     * @param b 字节数组
+     * @param offset 要转换的起始位置
+     * @param len 要转换的长度
+     * @param encoding 编码方式
+     * @return 如果encoding不支持,返回一个缺省编码的字符串
+     */
+    public static String getString(byte[] b, int offset, int len, String encoding) {
+        try {
+            return new String(b, offset, len, encoding);
+        } catch (UnsupportedEncodingException e) {
+            return new String(b, offset, len);
+        }
+    }
+    
+    /**
+     * @param ip ip的字节数组形式
+     * @return 字符串形式的ip
+     */
+    public static String getIpStringFromBytes(byte[] ip) {
+        StringBuffer sb = new StringBuffer();
+        sb.append(ip[0] & 0xFF);
+        sb.append('.');       
+        sb.append(ip[1] & 0xFF);
+        sb.append('.');       
+        sb.append(ip[2] & 0xFF);
+        sb.append('.');       
+        sb.append(ip[3] & 0xFF);
+        return sb.toString();
+    }
+} 

BIN
src/main/java/com/key/common/plugs/ipaddr/qqwry.dat


+ 255 - 0
src/main/java/com/key/common/plugs/itextpdf/Demo4URL2PDF.java

@@ -0,0 +1,255 @@
+package com.key.common.plugs.itextpdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jsoup.Jsoup;
+
+import com.itextpdf.text.BaseColor;
+import com.itextpdf.text.Chapter;
+import com.itextpdf.text.Chunk;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.Element;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.PageSize;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.Section;
+import com.itextpdf.text.WritableDirectElement;
+import com.itextpdf.text.pdf.BaseFont;
+import com.itextpdf.text.pdf.PdfWriter;
+import com.itextpdf.text.pdf.draw.LineSeparator;
+import com.itextpdf.tool.xml.ElementHandler;
+import com.itextpdf.tool.xml.Writable;
+import com.itextpdf.tool.xml.XMLWorkerHelper;
+import com.itextpdf.tool.xml.pipeline.WritableElement;
+
+/**
+ * HTML文件转换为PDF
+ * 
+ * @author <a href="http://www.micmiu.com">Michael Sun</a>
+ */
+public class Demo4URL2PDF {
+
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) throws Exception {
+		String blogURL = "http://www.micmiu.com/os/linux/shell-dev-null/";
+
+		// 直接把网页内容转为PDF文件
+		String pdfFile = "D:/Documents/demo-URL.pdf";
+		Demo4URL2PDF.parseURL2PDFFile(pdfFile, blogURL);
+
+		// 把网页内容转为PDF中的Elements
+		String pdfFile2 = "D:/Documents/demo-URL2.pdf";
+		Demo4URL2PDF.parseURL2PDFElement(pdfFile2, blogURL);
+	}
+
+	/**
+	 * 根据URL提前blog的基本信息,返回结果>>:[主题 ,分类,日期,内容]等.
+	 * 
+	 * @param blogURL
+	 * @return
+	 * @throws Exception
+	 */
+	public static String[] extractBlogInfo(String blogURL) throws Exception {
+		String[] info = new String[4];
+		org.jsoup.nodes.Document doc = Jsoup.connect(blogURL).get();
+		org.jsoup.nodes.Element e_title = doc.select("h2.title").first();
+		info[0] = e_title.text();
+
+		org.jsoup.nodes.Element e_category = doc.select("a[rel=category tag]")
+				.first();
+		info[1] = e_category.attr("href").replace("http://www.micmiu.com/", "");
+
+		org.jsoup.nodes.Element e_date = doc.select("span.post-info-date")
+				.first();
+
+		String dateStr = e_date.text().split("日期")[1].trim();
+		info[2] = dateStr;
+		org.jsoup.nodes.Element entry = doc.select("div.entry").first();
+		info[3] = formatContentTag(entry);
+
+		return info;
+	}
+
+	/**
+	 * 格式化 img标签
+	 * 
+	 * @param entry
+	 * @return
+	 */
+	private static String formatContentTag(org.jsoup.nodes.Element entry) {
+		try {
+			entry.select("div").remove();
+			// 把 <a href="*.jpg" ><img src="*.jpg"/></a> 替换为 <img
+			// src="*.jpg"/>
+			for (org.jsoup.nodes.Element imgEle : entry
+					.select("a[href~=(?i)\\.(png|jpe?g)]")) {
+				imgEle.replaceWith(imgEle.select("img").first());
+			}
+			return entry.html();
+		} catch (Exception e) {
+			return "";
+		}
+	}
+
+	/**
+	 * 把String 转为 InputStream
+	 * 
+	 * @param content
+	 * @return
+	 */
+	public static InputStream parse2Stream(String content) {
+		try {
+			ByteArrayInputStream stream = new ByteArrayInputStream(
+					content.getBytes("utf-8"));
+			return stream;
+		} catch (Exception e) {
+
+			return null;
+		}
+	}
+
+	/**
+	 * 直接把网页内容转为PDF文件
+	 * 
+	 * @param fileName
+	 * @throws Exception
+	 */
+	public static void parseURL2PDFFile(String pdfFile, String blogURL)
+			throws Exception {
+
+		BaseFont bfCN = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
+				false);
+		// 中文字体定义
+		Font chFont = new Font(bfCN, 14, Font.NORMAL, BaseColor.BLUE);
+		Font secFont = new Font(bfCN, 12, Font.NORMAL, new BaseColor(0, 204,
+				255));
+		Font textFont = new Font(bfCN, 12, Font.NORMAL, BaseColor.BLACK);
+
+		Document document = new Document();
+		PdfWriter pdfwriter = PdfWriter.getInstance(document,
+				new FileOutputStream(pdfFile));
+		pdfwriter.setViewerPreferences(PdfWriter.HideToolbar);
+		document.open();
+
+		String[] blogInfo = extractBlogInfo(blogURL);
+
+		int chNum = 1;
+		Chapter chapter = new Chapter(new Paragraph("URL转PDF测试", chFont),
+				chNum++);
+
+		Section section = chapter
+				.addSection(new Paragraph(blogInfo[0], secFont));
+		section.setIndentation(10);
+		section.setIndentationLeft(10);
+		section.setBookmarkOpen(false);
+		section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
+		section.add(new Chunk("分类:" + blogInfo[1] + " 日期:" + blogInfo[2],
+				textFont));
+
+		LineSeparator line = new LineSeparator(1, 100, new BaseColor(204, 204,
+				204), Element.ALIGN_CENTER, -2);
+		Paragraph p_line = new Paragraph(" ");
+		p_line.add(line);
+		section.add(p_line);
+		section.add(Chunk.NEWLINE);
+
+		document.add(chapter);
+
+		// html文件
+		XMLWorkerHelper.getInstance().parseXHtml(pdfwriter, document,
+				parse2Stream(blogInfo[3]));
+
+		document.close();
+	}
+
+	/**
+	 * 把网页内容转为PDF中的Elements
+	 * 
+	 * @param pdfFile
+	 * @param htmlFileStream
+	 */
+	public static void parseURL2PDFElement(String pdfFile, String blogURL) {
+		try {
+			Document document = new Document(PageSize.A4);
+
+			FileOutputStream outputStream = new FileOutputStream(pdfFile);
+			PdfWriter pdfwriter = PdfWriter.getInstance(document, outputStream);
+			// pdfwriter.setViewerPreferences(PdfWriter.HideToolbar);
+			document.open();
+
+			BaseFont bfCN = BaseFont.createFont("STSongStd-Light",
+					"UniGB-UCS2-H", false);
+			// 中文字体定义
+			Font chFont = new Font(bfCN, 14, Font.NORMAL, BaseColor.BLUE);
+			Font secFont = new Font(bfCN, 12, Font.NORMAL, new BaseColor(0,
+					204, 255));
+			Font textFont = new Font(bfCN, 12, Font.NORMAL, BaseColor.BLACK);
+
+			int chNum = 1;
+			Chapter chapter = new Chapter(new Paragraph("URL转PDF元素,便于追加其他内容",
+					chFont), chNum++);
+
+			String[] blogInfo = extractBlogInfo(blogURL);
+
+			Section section = chapter.addSection(new Paragraph(blogInfo[0],
+					secFont));
+
+			section.setIndentation(10);
+			section.setIndentationLeft(10);
+			section.setBookmarkOpen(false);
+			section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
+			section.add(new Chunk("分类:" + blogInfo[1] + " 发表日期:" + blogInfo[2],
+					textFont));
+			LineSeparator line = new LineSeparator(1, 100, new BaseColor(204,
+					204, 204), Element.ALIGN_CENTER, -2);
+			Paragraph p_line = new Paragraph();
+			p_line.add(line);
+			section.add(p_line);
+			section.add(Chunk.NEWLINE);
+
+			final List<Element> pdfeleList = new ArrayList<Element>();
+			ElementHandler elemH = new ElementHandler() {
+
+				public void add(final Writable w) {
+					if (w instanceof WritableElement) {
+						pdfeleList.addAll(((WritableElement) w).elements());
+					}
+
+				}
+			};
+			XMLWorkerHelper.getInstance().parseXHtml(elemH,
+					new InputStreamReader(parse2Stream(blogInfo[3]), "utf-8"));
+
+			List<Element> list = new ArrayList<Element>();
+			for (Element ele : pdfeleList) {
+				if (ele instanceof LineSeparator
+						|| ele instanceof WritableDirectElement) {
+					continue;
+				}
+				list.add(ele);
+			}
+			section.addAll(list);
+
+			section = chapter.addSection(new Paragraph("继续添加章节", secFont));
+
+			section.setIndentation(10);
+			section.setIndentationLeft(10);
+			section.setBookmarkOpen(false);
+			section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
+			section.add(new Chunk("测试URL转为PDF元素,方便追加其他内容", textFont));
+
+			document.add(chapter);
+			document.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+	}
+}

+ 255 - 0
src/main/java/com/key/common/plugs/itextpdf/Demo5URL2PDF.java

@@ -0,0 +1,255 @@
+package com.key.common.plugs.itextpdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jsoup.Jsoup;
+
+import com.itextpdf.text.BaseColor;
+import com.itextpdf.text.Chapter;
+import com.itextpdf.text.Chunk;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.Element;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.PageSize;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.Section;
+import com.itextpdf.text.WritableDirectElement;
+import com.itextpdf.text.pdf.BaseFont;
+import com.itextpdf.text.pdf.PdfWriter;
+import com.itextpdf.text.pdf.draw.LineSeparator;
+import com.itextpdf.tool.xml.ElementHandler;
+import com.itextpdf.tool.xml.Writable;
+import com.itextpdf.tool.xml.XMLWorkerHelper;
+import com.itextpdf.tool.xml.pipeline.WritableElement;
+
+/**
+ * HTML文件转换为PDF
+ * 
+ * @author <a href="http://www.micmiu.com">Michael Sun</a>
+ */
+public class Demo5URL2PDF {
+
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) throws Exception {
+		String blogURL = "http://localhost:8080/survey/pdfTest.jsp";
+
+		// 直接把网页内容转为PDF文件
+		String pdfFile = "D:/Documents/demo-URL.pdf";
+		Demo5URL2PDF.parseURL2PDFFile(pdfFile, blogURL);
+
+		// 把网页内容转为PDF中的Elements
+		String pdfFile2 = "D:/Documents/demo-URL2.pdf";
+		Demo5URL2PDF.parseURL2PDFElement(pdfFile2, blogURL);
+	}
+
+	/**
+	 * 根据URL提前blog的基本信息,返回结果>>:[主题 ,分类,日期,内容]等.
+	 * 
+	 * @param blogURL
+	 * @return
+	 * @throws Exception
+	 */
+	public static String[] extractBlogInfo(String blogURL) throws Exception {
+		String[] info = new String[4];
+		org.jsoup.nodes.Document doc = Jsoup.connect(blogURL).get();
+		org.jsoup.nodes.Element e_title = doc.select("h2.title").first();
+		info[0] = e_title.text();
+
+		org.jsoup.nodes.Element e_category = doc.select("a[rel=category tag]")
+				.first();
+		info[1] = e_category.attr("href").replace("http://www.micmiu.com/", "");
+
+		org.jsoup.nodes.Element e_date = doc.select("span.post-info-date")
+				.first();
+
+		String dateStr = e_date.text().split("日期")[1].trim();
+		info[2] = dateStr;
+		org.jsoup.nodes.Element entry = doc.select("div.entry").first();
+		info[3] = formatContentTag(entry);
+
+		return info;
+	}
+
+	/**
+	 * 格式化 img标签
+	 * 
+	 * @param entry
+	 * @return
+	 */
+	private static String formatContentTag(org.jsoup.nodes.Element entry) {
+		try {
+			entry.select("div").remove();
+			// 把 <a href="*.jpg" ><img src="*.jpg"/></a> 替换为 <img
+			// src="*.jpg"/>
+			for (org.jsoup.nodes.Element imgEle : entry
+					.select("a[href~=(?i)\\.(png|jpe?g)]")) {
+				imgEle.replaceWith(imgEle.select("img").first());
+			}
+			return entry.html();
+		} catch (Exception e) {
+			return "";
+		}
+	}
+
+	/**
+	 * 把String 转为 InputStream
+	 * 
+	 * @param content
+	 * @return
+	 */
+	public static InputStream parse2Stream(String content) {
+		try {
+			ByteArrayInputStream stream = new ByteArrayInputStream(
+					content.getBytes("utf-8"));
+			return stream;
+		} catch (Exception e) {
+
+			return null;
+		}
+	}
+
+	/**
+	 * 直接把网页内容转为PDF文件
+	 * 
+	 * @param fileName
+	 * @throws Exception
+	 */
+	public static void parseURL2PDFFile(String pdfFile, String blogURL)
+			throws Exception {
+
+		BaseFont bfCN = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
+				false);
+		// 中文字体定义
+		Font chFont = new Font(bfCN, 14, Font.NORMAL, BaseColor.BLUE);
+		Font secFont = new Font(bfCN, 12, Font.NORMAL, new BaseColor(0, 204,
+				255));
+		Font textFont = new Font(bfCN, 12, Font.NORMAL, BaseColor.BLACK);
+
+		Document document = new Document();
+		PdfWriter pdfwriter = PdfWriter.getInstance(document,
+				new FileOutputStream(pdfFile));
+		pdfwriter.setViewerPreferences(PdfWriter.HideToolbar);
+		document.open();
+
+		String[] blogInfo = extractBlogInfo(blogURL);
+
+		int chNum = 1;
+		Chapter chapter = new Chapter(new Paragraph("URL转PDF测试", chFont),
+				chNum++);
+
+		Section section = chapter
+				.addSection(new Paragraph(blogInfo[0], secFont));
+		section.setIndentation(10);
+		section.setIndentationLeft(10);
+		section.setBookmarkOpen(false);
+		section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
+		section.add(new Chunk("分类:" + blogInfo[1] + " 日期:" + blogInfo[2],
+				textFont));
+
+		LineSeparator line = new LineSeparator(1, 100, new BaseColor(204, 204,
+				204), Element.ALIGN_CENTER, -2);
+		Paragraph p_line = new Paragraph(" ");
+		p_line.add(line);
+		section.add(p_line);
+		section.add(Chunk.NEWLINE);
+
+		document.add(chapter);
+
+		// html文件
+		XMLWorkerHelper.getInstance().parseXHtml(pdfwriter, document,
+				parse2Stream(blogInfo[3]));
+
+		document.close();
+	}
+
+	/**
+	 * 把网页内容转为PDF中的Elements
+	 * 
+	 * @param pdfFile
+	 * @param htmlFileStream
+	 */
+	public static void parseURL2PDFElement(String pdfFile, String blogURL) {
+		try {
+			Document document = new Document(PageSize.A4);
+
+			FileOutputStream outputStream = new FileOutputStream(pdfFile);
+			PdfWriter pdfwriter = PdfWriter.getInstance(document, outputStream);
+			// pdfwriter.setViewerPreferences(PdfWriter.HideToolbar);
+			document.open();
+
+			BaseFont bfCN = BaseFont.createFont("STSongStd-Light",
+					"UniGB-UCS2-H", false);
+			// 中文字体定义
+			Font chFont = new Font(bfCN, 14, Font.NORMAL, BaseColor.BLUE);
+			Font secFont = new Font(bfCN, 12, Font.NORMAL, new BaseColor(0,
+					204, 255));
+			Font textFont = new Font(bfCN, 12, Font.NORMAL, BaseColor.BLACK);
+
+			int chNum = 1;
+			Chapter chapter = new Chapter(new Paragraph("URL转PDF元素,便于追加其他内容",
+					chFont), chNum++);
+
+			String[] blogInfo = extractBlogInfo(blogURL);
+
+			Section section = chapter.addSection(new Paragraph(blogInfo[0],
+					secFont));
+
+			section.setIndentation(10);
+			section.setIndentationLeft(10);
+			section.setBookmarkOpen(false);
+			section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
+			section.add(new Chunk("分类:" + blogInfo[1] + " 发表日期:" + blogInfo[2],
+					textFont));
+			LineSeparator line = new LineSeparator(1, 100, new BaseColor(204,
+					204, 204), Element.ALIGN_CENTER, -2);
+			Paragraph p_line = new Paragraph();
+			p_line.add(line);
+			section.add(p_line);
+			section.add(Chunk.NEWLINE);
+
+			final List<Element> pdfeleList = new ArrayList<Element>();
+			ElementHandler elemH = new ElementHandler() {
+
+				public void add(final Writable w) {
+					if (w instanceof WritableElement) {
+						pdfeleList.addAll(((WritableElement) w).elements());
+					}
+
+				}
+			};
+			XMLWorkerHelper.getInstance().parseXHtml(elemH,
+					new InputStreamReader(parse2Stream(blogInfo[3]), "utf-8"));
+
+			List<Element> list = new ArrayList<Element>();
+			for (Element ele : pdfeleList) {
+				if (ele instanceof LineSeparator
+						|| ele instanceof WritableDirectElement) {
+					continue;
+				}
+				list.add(ele);
+			}
+			section.addAll(list);
+
+			section = chapter.addSection(new Paragraph("继续添加章节", secFont));
+
+			section.setIndentation(10);
+			section.setIndentationLeft(10);
+			section.setBookmarkOpen(false);
+			section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
+			section.add(new Chunk("测试URL转为PDF元素,方便追加其他内容", textFont));
+
+			document.add(chapter);
+			document.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+	}
+}

+ 119 - 0
src/main/java/com/key/common/plugs/itextpdf/ItextpdfTest.java

@@ -0,0 +1,119 @@
+package com.key.common.plugs.itextpdf;
+
+import java.io.FileOutputStream;
+
+import com.itextpdf.text.BaseColor;
+import com.itextpdf.text.Chapter;
+import com.itextpdf.text.Document;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.FontFactory;
+import com.itextpdf.text.Image;
+import com.itextpdf.text.PageSize;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.Section;
+import com.itextpdf.text.pdf.BaseFont;
+import com.itextpdf.text.pdf.PdfWriter;
+
+public class ItextpdfTest {
+	
+			public static void main(String[] args) {
+				try{
+					ItextpdfTest.writeSimplePdf();
+					ItextpdfTest.writeCharpter();
+				}catch(Exception e){
+					e.printStackTrace();
+				}
+			}
+			
+			public static void writeSimplePdf() throws Exception{
+				//1.新建document对象
+				//第一个参数是页面大小。接下来的参数分别是左、右、上和下页边距。
+				Document document = new Document(PageSize.A4, 50, 50, 50, 50);
+				//2.建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
+				//创建 PdfWriter 对象 第一个参数是对文档对象的引用,第二个参数是文件的实际名称,在该名称中还会给出其输出路径。
+				PdfWriter writer = PdfWriter.getInstance(document, 	new FileOutputStream("D:\\Documents\\ITextTest.pdf"));
+				//3.打开文档
+				document.open();		
+				//4.向文档中添加内容
+				//通过 com.lowagie.text.Paragraph 来添加文本。可以用文本及其默认的字体、颜色、大小等等设置来创建一个默认段落
+				BaseFont bfChinese = BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
+				Font fontChinese = new Font(bfChinese, 22, Font.BOLD, BaseColor.BLACK);
+				
+				document.add(new Paragraph("sdfsdfsd全是中文显示了没.fsdfsfs",fontChinese));
+				document.add(new Paragraph("Some more text on the 	first page with different color and font type.",
+						FontFactory.getFont(FontFactory.COURIER, 14, Font.BOLD, new BaseColor(255, 150, 200))));
+				Paragraph pragraph=new Paragraph("你这里有中亠好", fontChinese);
+				document.add(pragraph);
+				
+				//图像支持格式 GIF, Jpeg, PNG, wmf
+				Image gif = Image.getInstance("F:/keyworkspace/survey/WebRoot/images/logo/snlogo.png");
+				gif.setBorder(5);
+				gif.scaleAbsolute(30,30);
+				gif.setAlignment(Image.RIGHT|Image.TEXTWRAP);
+				document.add(gif);
+				Paragraph pragraph11=new Paragraph("你这里有中亠好你这里有中亠好你这里有中亠好你这里有中亠好你这里有中亠好你这里有中亠好你这里有中亠好你这里有中亠好你这里有中亠好你这里有中亠好", fontChinese);
+				document.add(pragraph11);
+				
+				Image gif15 = Image.getInstance("F:/keyworkspace/survey/WebRoot/images/logo/snlogo.png");
+	//			gif15.setBorder(50);
+				gif15.setBorder(Image.BOX);
+				gif15.setBorderColor(BaseColor.RED);
+	//			gif15.setBorderColorBottom(borderColorBottom)
+				gif15.setBorderWidth(1);
+				gif15.scalePercent(50);
+				document.add(gif15);
+				//5.关闭文档
+				document.close();
+			}
+			
+			/**
+			 * 添加含有章节的pdf文件
+			 * @throws Exception
+			 */
+			public static void writeCharpter() throws Exception{
+				//新建document对象  第一个参数是页面大小。接下来的参数分别是左、右、上和下页边距。
+				Document document = new Document(PageSize.A4, 20, 20, 20, 20);
+				//建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
+				PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream("D:\\Documents\\ITextTestCharpter.pdf"));
+				//打开文件
+				document.open();
+				//标题
+				document.addTitle("Hello mingri example");
+				//作者
+				document.addAuthor("wolf");
+				//主题
+				document.addSubject("This example explains how to add metadata.");
+				document.addKeywords("iText, Hello mingri");
+				document.addCreator("My program using iText");
+	//			document.newPage();
+				//向文档中添加内容
+				document.add(new Paragraph("\n"));
+				document.add(new Paragraph("\n"));
+				document.add(new Paragraph("\n"));
+				document.add(new Paragraph("\n"));
+				document.add(new Paragraph("\n"));
+				document.add(new Paragraph("First page of the document."));
+				document.add(new Paragraph("First page of the document."));
+				document.add(new Paragraph("First page of the document."));
+				document.add(new Paragraph("First page of the document."));
+				document.add(new Paragraph("Some more text on the first page with different color and font type.",
+								FontFactory.getFont(FontFactory.defaultEncoding, 10,Font.BOLD, new BaseColor(0, 0, 0))));
+				Paragraph title1 = new Paragraph("Chapter 1", 
+								FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new BaseColor(0, 0,255)));
+				//新建章节
+				Chapter chapter1 = new Chapter(title1, 1);
+				chapter1.setNumberDepth(0);
+				Paragraph title11 = new Paragraph("This is Section 1 in Chapter 1",
+						FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD,new BaseColor(255, 0, 0)));
+				Section section1 = chapter1.addSection(title11);
+				Paragraph someSectionText = new Paragraph("This text comes as part of section 1 of chapter 1.");
+				section1.add(someSectionText);
+				someSectionText = new Paragraph("Following is a 3 X 2 table.");
+				section1.add(someSectionText);
+				document.add(chapter1);
+				//关闭文档
+				document.close();
+			}
+	
+}
+

+ 99 - 0
src/main/java/com/key/common/plugs/itextpdf/PDFUtil.java

@@ -0,0 +1,99 @@
+package com.key.common.plugs.itextpdf;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.w3c.tidy.Configuration;
+import org.w3c.tidy.Tidy;
+import org.xhtmlrenderer.pdf.ITextFontResolver;
+import org.xhtmlrenderer.pdf.ITextRenderer;
+
+import com.itextpdf.text.pdf.BaseFont;
+
+public class PDFUtil {
+	
+	public static void main(String[] args) {
+		String url="http://localhost:8080/survey/pdfTest.jsp";
+		try {
+			PDFUtil.exportPdfFile(url);
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+	}
+	
+	// 导出pdf add by huangt 2012.6.1
+	public static File exportPdfFile(String urlStr) throws Exception {
+		// String outputFile = this.fileRoot + "/" +
+		// ServiceConstants.DIR_PUBINFO_EXPORT + "/" + getFileName() + ".pdf";
+		String outputFile = "D:/Documents/test3.pdf";
+		OutputStream os = new FileOutputStream(outputFile);
+		ITextRenderer renderer = new ITextRenderer();
+
+		String str = getHtmlFile(urlStr);
+		renderer.setDocumentFromString(str);
+		ITextFontResolver fontResolver = renderer.getFontResolver();
+
+		fontResolver.addFont("F:/keyworkspace/survey/src/conf/itextpdf/simsun.ttc",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+		// // 宋体字
+		fontResolver.addFont("F:/keyworkspace/survey/src/conf/itextpdf/ARIALUNI.TTF",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);// 宋体字
+		renderer.layout();
+
+		renderer.createPDF(os);
+
+		System.out.println("转换成功!");
+		os.flush();
+		os.close();
+		return new File(outputFile);
+
+	}
+
+	// 读取页面内容 add by huangt 2012.6.1
+	public static String getHtmlFile(String urlStr) throws Exception {
+		URL url;
+		if (urlStr.indexOf("?") != -1) {
+			urlStr = urlStr + "&locale="
+					+ LocaleContextHolder.getLocale().toString();
+		} else {
+			urlStr = urlStr + "?locale="
+					+ LocaleContextHolder.getLocale().toString();
+		}
+		url = new URL(urlStr);
+
+		URLConnection uc = url.openConnection();
+		InputStream is = uc.getInputStream();
+
+		Tidy tidy = new Tidy();
+
+		OutputStream os2 = new ByteArrayOutputStream();
+		tidy.setXHTML(true); // 设定输出为xhtml(还可以输出为xml)
+		tidy.setCharEncoding(Configuration.UTF8); // 设定编码以正常转换中文
+		tidy.setTidyMark(false); // 不设置它会在输出的文件中给加条meta信息
+		tidy.setXmlPi(true); // 让它加上<?xml version="1.0"?>
+		tidy.setIndentContent(true); // 缩进,可以省略,只是让格式看起来漂亮一些
+		tidy.parse(is, os2);
+
+		is.close();
+
+		// 解决乱码 --将转换后的输出流重新读取改变编码
+		String temp;
+		StringBuffer sb = new StringBuffer();
+		BufferedReader in = new BufferedReader(new InputStreamReader(
+				new ByteArrayInputStream(
+						((ByteArrayOutputStream) os2).toByteArray()), "utf-8"));
+		while ((temp = in.readLine()) != null) {
+			sb.append(temp);
+		}
+		System.out.println(sb.toString());
+		return sb.toString();
+	}
+}

+ 84 - 0
src/main/java/com/key/common/plugs/itextpdf/WordTest.java

@@ -0,0 +1,84 @@
+package com.key.common.plugs.itextpdf;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.apache.poi.poifs.filesystem.DirectoryEntry;
+import org.apache.poi.poifs.filesystem.DocumentEntry;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+
+public class WordTest {
+	/**
+	 * 读取html文件到word
+	 * 
+	 * @param filepath
+	 *            html文件的路径
+	 * @return
+	 * @throws Exception
+	 */
+	public boolean writeWordFile(String filepath) throws Exception {
+		boolean flag = false;
+		ByteArrayInputStream bais = null;
+		FileOutputStream fos = null;
+		String path = "D:/"; // 根据实际情况写路径
+		try {
+			if (!"".equals(path)) {
+				File fileDir = new File(path);
+				if (fileDir.exists()) {
+					String content = readFile(filepath);
+					byte b[] = content.getBytes();
+					bais = new ByteArrayInputStream(b);
+					POIFSFileSystem poifs = new POIFSFileSystem();
+					DirectoryEntry directory = poifs.getRoot();
+					DocumentEntry documentEntry = directory.createDocument(
+							"WordDocument", bais);
+					fos = new FileOutputStream(path + "temp1.doc");
+					poifs.writeFilesystem(fos);
+					bais.close();
+					fos.close();
+				}
+			}
+
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			if (fos != null)
+				fos.close();
+			if (bais != null)
+				bais.close();
+		}
+		return flag;
+	}
+
+	/**
+	 * 读取html文件到字符串
+	 * 
+	 * @param filename
+	 * @return
+	 * @throws Exception
+	 */
+	public String readFile(String filename) throws Exception {
+		StringBuffer buffer = new StringBuffer("");
+		BufferedReader br = null;
+		try {
+			br = new BufferedReader(new FileReader(filename));
+			buffer = new StringBuffer();
+			while (br.ready())
+				buffer.append((char) br.read());
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			if (br != null)
+				br.close();
+		}
+		return buffer.toString(); 
+	}
+
+	public static void main(String[] args) throws Exception {
+		new WordTest().writeWordFile("D:/ttpp.htm");
+	}
+}

+ 100 - 0
src/main/java/com/key/common/plugs/jcaptcha/CaptchaEngineEx.java

@@ -0,0 +1,100 @@
+package com.key.common.plugs.jcaptcha;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.image.ImageFilter;
+
+import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;
+import com.octo.captcha.component.image.backgroundgenerator.FunkyBackgroundGenerator;
+import com.octo.captcha.component.image.backgroundgenerator.GradientBackgroundGenerator;
+import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;
+import com.octo.captcha.component.image.color.ColorGenerator;
+import com.octo.captcha.component.image.color.RandomListColorGenerator;
+import com.octo.captcha.component.image.deformation.ImageDeformation;
+import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;
+import com.octo.captcha.component.image.fontgenerator.FontGenerator;
+import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
+import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;
+import com.octo.captcha.component.image.textpaster.TextPaster;
+import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;
+import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;
+import com.octo.captcha.component.image.wordtoimage.WordToImage;
+import com.octo.captcha.component.word.FileDictionary;
+import com.octo.captcha.component.word.wordgenerator.ComposeDictionaryWordGenerator;
+import com.octo.captcha.component.word.wordgenerator.WordGenerator;
+import com.octo.captcha.engine.image.ListImageCaptchaEngine;
+import com.octo.captcha.image.gimpy.GimpyFactory;
+import com.sun.image.codec.jpeg.ImageFormatException;
+
+public class CaptchaEngineEx extends ListImageCaptchaEngine {
+
+	/*protected void buildInitialFactories() {
+		int minWordLength = 4;
+		int maxWordLength = 5;
+		int fontSize = 50;
+		int imageWidth = 250;
+		int imageHeight = 100;
+
+		WordGenerator wordGenerator = new RandomWordGenerator(
+				"0123456789abcdefghijklmnopqrstuvwxyz");
+
+		TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength,
+				maxWordLength, new RandomListColorGenerator(new Color[] {
+						new Color(23, 170, 27), new Color(220, 34, 11),
+						new Color(23, 67, 172) }), new TextDecorator[] {});
+		BackgroundGenerator background = new UniColorBackgroundGenerator(
+				imageWidth, imageHeight, Color.white);
+		FontGenerator font = new RandomFontGenerator(fontSize, fontSize,
+				new Font[] { new Font("nyala", Font.BOLD, fontSize),
+						new Font("Bell MT", Font.PLAIN, fontSize),
+						new Font("Credit valley", Font.BOLD, fontSize) });
+
+		ImageDeformation postDef = new ImageDeformationByFilters(
+				new ImageFilter[] {});
+		ImageDeformation backDef = new ImageDeformationByFilters(
+				new ImageFilter[] {});
+		ImageDeformation textDef = new ImageDeformationByFilters(
+				new ImageFilter[] {});
+
+		WordToImage word2image = new DeformedComposedWordToImage(font,
+				background, randomPaster, backDef, textDef, postDef);
+		addFactory(new GimpyFactory(wordGenerator, word2image));
+
+	}*/
+
+	   protected void buildInitialFactories() {  
+	        int minWordLength = 4;  
+	        int maxWordLength = 5;  
+	        /*int fontSize = 50;  
+	        int imageWidth = 250;  
+	        int imageHeight = 100;*/
+	        int fontSize = 30;
+	        int imageWidth = 120;  
+	        int imageHeight = 50;
+	        WordGenerator dictionnaryWords = new ComposeDictionaryWordGenerator(new FileDictionary("toddlist"));  
+	        
+	        // word2image components  
+	        TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength,  
+	                maxWordLength, new RandomListColorGenerator(new Color[] {  
+	                        new Color(23, 170, 27), new Color(220, 34, 11),  
+	                        new Color(23, 67, 172) }), new TextDecorator[] {});  
+	       BackgroundGenerator background = new UniColorBackgroundGenerator(
+	                imageWidth, imageHeight, Color.white);
+//	        ColorGenerator colorGenerator=new RandomListColorGenerator(new Color[]{new Color(235, 234, 235),new Color(255, 255, 255)});
+//	        BackgroundGenerator background=new FunkyBackgroundGenerator(imageWidth, imageHeight,colorGenerator);
+	        FontGenerator font = new RandomFontGenerator(fontSize, fontSize,  
+	                new Font[] { new Font("nyala", Font.BOLD, fontSize),  
+	                        new Font("Bell MT", Font.PLAIN, fontSize),  
+	                        new Font("Credit valley", Font.BOLD, fontSize) });  
+	        ImageDeformation postDef = new ImageDeformationByFilters(  
+	                new ImageFilter[] {});  
+	        ImageDeformation backDef = new ImageDeformationByFilters(  
+	                new ImageFilter[] {});  
+	        ImageDeformation textDef = new ImageDeformationByFilters(  
+	                new ImageFilter[] {});  
+	  
+	        WordToImage word2image = new DeformedComposedWordToImage(font,  
+	                background, randomPaster, backDef, textDef, postDef);  
+	        addFactory(new GimpyFactory(dictionnaryWords, word2image));  
+	    }  
+}

+ 38 - 0
src/main/java/com/key/common/plugs/jms/advanced/AdvancedNotifyMessageListener.java

@@ -0,0 +1,38 @@
+package com.key.common.plugs.jms.advanced;
+
+import javax.jms.MapMessage;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 消息的异步被动接收者.
+ * 
+ * 使用Spring的MessageListenerContainer侦听消息并调用本Listener进行处理.
+ * 
+ * @author KeYuan
+ *
+ */
+public class AdvancedNotifyMessageListener implements MessageListener {
+
+	private static Logger logger = LoggerFactory.getLogger(AdvancedNotifyMessageListener.class);
+
+	/**
+	 * MessageListener回调函数.
+	 */
+	@Override
+	public void onMessage(Message message) {
+		try {
+			MapMessage mapMessage = (MapMessage) message;
+
+			System.out.println("消费消息");
+			//打印消息详情
+		/*	logger.info("UserName:" + mapMessage.getString("userName") + ", Email:" + mapMessage.getString("email")
+					+ ", ObjectType:" + mapMessage.getStringProperty("objectType"));*/
+		} catch (Exception e) {
+			logger.error("处理消息时发生异常.", e);
+		}
+	}
+}

+ 83 - 0
src/main/java/com/key/common/plugs/jms/advanced/AdvancedNotifyMessageProducer.java

@@ -0,0 +1,83 @@
+package com.key.common.plugs.jms.advanced;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MapMessage;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import com.key.common.base.entity.User;
+import org.apache.activemq.ScheduledMessage;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+
+/**
+ * JMS用户变更消息生产者.
+ * 
+ * 使用jmsTemplate将用户变更消息分别发送到queue与topic.
+ * 
+ * @author KeYuan
+ */
+public class AdvancedNotifyMessageProducer {
+
+	private JmsTemplate jmsTemplate;
+	private Destination notifyQueue;
+	private Destination notifyTopic;
+
+	public void sendQueue(final User user) {
+		sendMessage(user, notifyQueue);
+	}
+
+	public void sendTopic(final User user) {
+		sendMessage(user, notifyTopic);
+	}
+
+	/**
+	 * 使用jmsTemplate的send/MessageCreator()发送Map类型的消息并在Message中附加属性用于消息过滤.
+	 */
+	private void sendMessage(final User user, Destination destination) {
+		jmsTemplate.send(destination, new MessageCreator() {
+			@Override
+			public Message createMessage(Session session) throws JMSException {
+
+				MapMessage message = session.createMapMessage();
+				message.setString("userName", user.getName());
+				message.setString("email", user.getEmail());
+
+				message.setStringProperty("objectType", "user");
+
+				return message;
+			}
+		});
+	}
+
+	public void setJmsTemplate(JmsTemplate jmsTemplate) {
+		this.jmsTemplate = jmsTemplate;
+	}
+
+	public void setNotifyQueue(Destination notifyQueue) {
+		this.notifyQueue = notifyQueue;
+	}
+
+	public void setNotifyTopic(Destination nodifyTopic) {
+		this.notifyTopic = nodifyTopic;
+	}
+	
+	//test
+	public void sendMessage() {
+		jmsTemplate.send(notifyTopic, new MessageCreator() {
+			@Override
+			public Message createMessage(Session session) throws JMSException {
+
+				MapMessage message = session.createMapMessage();
+				
+				int delay=10*1000;
+				System.out.println("生产消消息");
+				message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY,	 delay);
+				message.setStringProperty("objectType", "user");
+
+				return message;
+			}
+		});
+	}
+}

+ 42 - 0
src/main/java/com/key/common/plugs/jms/jms/InvokeMessage.java

@@ -0,0 +1,42 @@
+package com.key.common.plugs.jms.jms;
+
+import java.io.Serializable;
+
+/** 
+ * 用来存储我们要发送消息的pojo 
+ * */  
+public class InvokeMessage implements Serializable{  
+      
+    private static final long serialVersionUID = 2L;  
+  
+    private String name;  
+      
+    private String operate;  
+      
+    private String msg;  
+  
+    public String getMsg() {  
+        return msg;  
+    }  
+  
+    public void setMsg(String msg) {  
+        this.msg = msg;  
+    }  
+  
+    public String getName() {  
+        return name;  
+    }  
+  
+    public void setName(String name) {  
+        this.name = name;  
+    }  
+  
+    public String getOperate() {  
+        return operate;  
+    }  
+  
+    public void setOperate(String operate) {  
+        this.operate = operate;  
+    }  
+      
+}

+ 29 - 0
src/main/java/com/key/common/plugs/jms/jms/InvokeMessageConsumer.java

@@ -0,0 +1,29 @@
+package com.key.common.plugs.jms.jms;
+
+import javax.jms.Message;
+
+/** 
+ *消费消息 
+ * @author kongqz 
+ */  
+public class InvokeMessageConsumer{  
+  
+    /** 
+     * @author Administrator 
+     * */  
+    public void printMyOut(InvokeMessage invokeMessage) {  
+        System.out.println("等待1秒再处理");  
+        /*try {
+            Thread.sleep(1000);  
+        } catch (InterruptedException e) {
+            e.printStackTrace();  
+        }  */
+        //System.out.println("执行业务操作["+invokeMessage.getName()+"],["+invokeMessage.getOperate()+"],["+invokeMessage.getMsg()+"]");
+        System.out.println("消息消费11");
+    }  
+    
+    public void printMyOut01(Message message){
+    	System.out.println("执行业务操作。。。");
+    }
+  
+}  

+ 85 - 0
src/main/java/com/key/common/plugs/jms/jms/InvokeMessageConverter.java

@@ -0,0 +1,85 @@
+package com.key.common.plugs.jms.jms;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.ObjectMessage;
+import javax.jms.Session;
+
+import org.apache.activemq.ScheduledMessage;
+import org.apache.activemq.command.ActiveMQObjectMessage;
+import org.springframework.jms.support.converter.MessageConversionException;
+import org.springframework.jms.support.converter.MessageConverter;
+
+/**
+ * @see MessageConverter 将要发送的pojo转化成activemq可以辨识的类型
+ */
+public class InvokeMessageConverter implements MessageConverter {
+	// 接收消息时候使用
+	public Object fromMessage(Message msg) throws JMSException,
+			MessageConversionException {
+		if (msg instanceof ObjectMessage) {
+			if (msg instanceof ObjectMessage) {
+				HashMap<String, byte[]> map = (HashMap<String, byte[]>) ((ObjectMessage) msg).getObjectProperty("Map");
+				if(map!=null){
+					try {
+						// POJO must implements Seralizable 
+						ByteArrayInputStream bis = new ByteArrayInputStream(map.get("InvokeMessage"));
+						ObjectInputStream ois = new ObjectInputStream(bis);
+						Object returnObject = ois.readObject();
+						return returnObject;
+					} catch (IOException e) {
+						System.out.println("fromMessage(Message)");
+						e.printStackTrace();
+
+					} catch (ClassNotFoundException e) {
+						System.out.println("fromMessage(Message)");
+						e.printStackTrace();
+					}
+				}else{
+					System.out.println("message is empty");
+				}
+			}
+		} else {
+			//throw new JMSException("Msg:[" + msg + "] is not Map");
+		}
+		return null;
+	}
+
+	// 发送消息时候使用
+	public Message toMessage(Object obj, Session session) throws JMSException,
+			MessageConversionException {
+
+		if (obj instanceof InvokeMessage) {
+			ActiveMQObjectMessage objMsg = (ActiveMQObjectMessage) session
+					.createObjectMessage();
+			long delay=5*1000;
+        	System.out.println("延时:"+delay/1000+"秒");
+        	System.out.println("msgId:"+objMsg.getJMSMessageID());
+        	objMsg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
+//        	objMsg.setExpiration(2000);
+        	
+			Map<String, byte[]> map = new HashMap<String, byte[]>();
+			try {
+				ByteArrayOutputStream bos = new ByteArrayOutputStream();
+				ObjectOutputStream oos = new ObjectOutputStream(bos);
+				oos.writeObject(obj);
+				map.put("InvokeMessage", bos.toByteArray());
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			objMsg.setObjectProperty("Map", map);
+			return objMsg;
+		} else {
+			throw new JMSException("Object:[" + obj + "] is not InvokeMessage");
+		}
+	}
+	
+}

+ 49 - 0
src/main/java/com/key/common/plugs/jms/jms/InvokeMessageProducer.java

@@ -0,0 +1,49 @@
+package com.key.common.plugs.jms.jms;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.ScheduledMessage;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+
+/**
+ * 用来发送消息
+ * @author Administrator
+ *
+ */
+public class InvokeMessageProducer {
+	private JmsTemplate template;
+
+	private Queue destination;
+
+	public void setTemplate(JmsTemplate template) {
+		this.template = template;
+	}
+
+	public void setDestination(Queue destination) {
+		this.destination = destination;
+	}
+
+	public void send(InvokeMessage invokeMessage) {
+		template.convertAndSend(this.destination, invokeMessage);
+	}
+	
+	public void send() {
+		template.send(this.destination, new MessageCreator() {
+			@Override
+			public Message createMessage(Session session) throws JMSException {
+				TextMessage message=session.createTextMessage();
+				System.out.println("发出消息,延时10秒.");
+				String msgId=message.getJMSMessageID();
+				System.out.println("msgId:"+msgId);
+				message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 20*1000);
+				message.setStringProperty("content", "内容content...");
+				return message;
+			}
+		});
+	}
+}

+ 64 - 0
src/main/java/com/key/common/plugs/jms/simple/NotifyMessageListener.java

@@ -0,0 +1,64 @@
+package com.key.common.plugs.jms.simple;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+
+import com.key.common.plugs.email.Email;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 消息的异步被动接收者.
+ * 
+ * 使用Spring的MessageListenerContainer侦听消息并调用本Listener进行处理.
+ * 
+ * @author KeYuan
+ *
+ */
+public class NotifyMessageListener implements MessageListener {
+
+	private static Logger logger = LoggerFactory.getLogger(NotifyMessageListener.class);
+
+//	@Autowired(required = false)
+//	private SimpleMailService simpleMailService;
+
+	/**
+	 * MessageListener回调函数.
+	 */
+	@Override
+	public void onMessage(Message message) {
+		try {
+			message.getPropertyNames();
+			/*MapMessage mapMessage = (MapMessage) message;
+			// 打印消息详情
+			String subject=mapMessage.getObject("subject").toString();
+			String to=mapMessage.getObject("to").toString();
+			String date=mapMessage.getObject("date").toString();
+			String username=mapMessage.getObject("username").toString();
+			String content=mapMessage.getObject("content").toString();*/
+			
+			String subject= "柯远";
+			String to="912114781@qq.com";
+			String date="2013-03-20";
+			String username="keyuan";
+			String content="activmq测试邮件";
+			//mapMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 15*1000);
+			System.out.println("收到了消息");
+			logger.info("subject:" + subject+";to:"+to+";date:"+date+";username:"+username+";content:"+content+";");
+			Email email=new Email();
+			email.setContent(content);
+			email.setDate(date);
+			email.setSubject(subject);
+			email.setTo(to);
+			email.setUsername(username);
+			// 发送邮件
+//			if (simpleMailService != null) {
+//				simpleMailService.sendNotificationMail("柯远。。。");
+//			}
+		} catch (JMSException e) {
+			logger.error(e.getMessage(), e);
+		}
+	}
+}

+ 116 - 0
src/main/java/com/key/common/plugs/jms/simple/NotifyMessageProducer.java

@@ -0,0 +1,116 @@
+package com.key.common.plugs.jms.simple;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import com.key.common.base.entity.User;
+import org.apache.activemq.ScheduledMessage;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+
+import com.key.common.plugs.email.Email;
+
+
+/**
+ * JMS用户变更消息生产者.
+ * 
+ * 使用jmsTemplate将用户变更消息分别发送到queue与topic.
+ * 
+ * @author KeYuan
+ */
+
+public class NotifyMessageProducer {
+	
+	private JmsTemplate jmsTemplate;
+	private Destination notifyQueue;
+	private Destination notifyTopic;
+	
+	public void sendQueue(final User user) {
+		sendMessage(user, notifyQueue);
+	}
+
+	public void sendTopic(final User user) {
+		sendMessage(user, notifyTopic);
+	}
+
+	/**
+	 * 使用jmsTemplate最简便的封装convertAndSend()发送Map类型的消息.
+	 */
+	private void sendMessage(User user, Destination destination) {
+		Map map = new HashMap();
+		map.put("userName", user.getName());
+		map.put("email", user.getEmail());
+
+		jmsTemplate.convertAndSend(destination, map);
+	}
+
+	public void setJmsTemplate(JmsTemplate jmsTemplate) {
+		this.jmsTemplate = jmsTemplate;
+	}
+
+	public void setNotifyQueue(Destination notifyQueue) {
+		this.notifyQueue = notifyQueue;
+	}
+
+	public void setNotifyTopic(Destination nodifyTopic) {
+		this.notifyTopic = nodifyTopic;
+	}
+	
+	public void sendQueue(final Email mail) {
+		sendMessage(mail, notifyQueue);
+	}
+
+	public void sendTopic(final Email mail) {
+		sendMessage(mail, notifyTopic);
+	}
+	
+	/**
+	 * 使用jmsTemplate最简便的封装convertAndSend()发送Map类型的消息.
+	 * @throws JMSException 
+	 */
+	private void sendMessage(Email mail, Destination destination) {
+		Map map = new HashMap();
+		/*map.put("subject", mail.getSubject());
+		map.put("to", mail.getTo());
+		map.put("date", mail.getDate());
+		map.put("username", mail.getUsername());
+		map.put("content", mail.getContent());*/
+		map.put("subject", "柯远");
+		map.put("to", "912114781@qq.com");
+		map.put("date", "2013-03-20");
+		map.put("username", "keyuan");
+		map.put("content", "activmq测试邮件");
+		jmsTemplate.convertAndSend(destination, map);
+		
+//		jmsTemplate.send(destination,new MessageCreator() {
+//			
+//			@Override
+//			public Message createMessage(Session session) throws JMSException {
+//				TextMessage	message=session.createTextMessage("textMsg....柯远");
+//				message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 65*1000);
+//				System.out.println("等65秒后再发");
+//				return message;
+//			}
+//		});
+		
+	}
+	
+	public void send(){
+		jmsTemplate.send(notifyQueue,new MessageCreator() {
+			@Override
+			public Message createMessage(Session session) throws JMSException {
+				TextMessage	message=session.createTextMessage("textMsg....柯远");
+				message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 65*1000);
+				System.out.println("等65秒后再发");
+				return message;
+			}
+		});
+	}
+	
+}

+ 81 - 0
src/main/java/com/key/common/plugs/mapper/CollectionMapper.java

@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2005-2011 springside.org.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 
+ * $Id: Fixtures.java 1593 2011-05-11 10:37:12Z calvinxiu $
+ */
+package com.key.common.plugs.mapper;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.lang.StringUtils;
+
+import com.key.common.utils.ReflectionUtils;
+
+/**
+ * 提出集合中的元素对象的属性(通过Getter函数),组合成新的集合.
+ *
+ */
+public class CollectionMapper {
+
+	/**
+	 * 提取集合中的对象的属性(通过Getter函数), 组合成Map.
+	 * 
+	 * @param collection 来源集合.
+	 * @param keyPropertyName 要提取为Map中的Key值的属性名.
+	 * @param valuePropertyName 要提取为Map中的Value值的属性名.
+	 */
+	public static Map extractToMap(final Collection collection, final String keyPropertyName,
+			final String valuePropertyName) {
+		Map map = new HashMap();
+
+		try {
+			for (Object obj : collection) {
+				map.put(PropertyUtils.getProperty(obj, keyPropertyName),
+						PropertyUtils.getProperty(obj, valuePropertyName));
+			}
+		} catch (Exception e) {
+			throw ReflectionUtils.convertReflectionExceptionToUnchecked(e);
+		}
+
+		return map;
+	}
+
+	/**
+	 * 提取集合中的对象的属性(通过Getter函数), 组合成List.
+	 * 
+	 * @param collection 来源集合.
+	 * @param propertyName 要提取的属性名.
+	 */
+	public static List extractToList(final Collection collection, final String propertyName) {
+		List list = new ArrayList();
+
+		try {
+			for (Object obj : collection) {
+				list.add(PropertyUtils.getProperty(obj, propertyName));
+			}
+		} catch (Exception e) {
+			throw ReflectionUtils.convertReflectionExceptionToUnchecked(e);
+		}
+
+		return list;
+	}
+
+	/**
+	 * 提取集合中的对象的属性(通过Getter函数), 组合成由分割符分隔的字符串.
+	 * 
+	 * @param collection 来源集合.
+	 * @param propertyName 要提取的属性名.
+	 * @param separator 分隔符.
+	 */
+	public static String extractToString(final Collection collection, final String propertyName, final String separator) {
+		List list = extractToList(collection, propertyName);
+		return StringUtils.join(list, separator);
+	}
+}

+ 96 - 0
src/main/java/com/key/common/plugs/mapper/ObjectMapper.java

@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2005-2011 springside.org.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 
+ * $Id: ObjectMapper.java 1627 2011-05-23 16:23:18Z calvinxiu $
+ */
+package com.key.common.plugs.mapper;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.beanutils.ConvertUtils;
+import org.apache.commons.beanutils.converters.DateConverter;
+import org.apache.velocity.util.StringUtils;
+import org.dozer.DozerBeanMapper;
+
+import com.google.common.collect.Lists;
+import com.key.common.utils.ReflectionUtils;
+
+/**
+ * 对象转换工具类.
+ * 1.封装Dozer, 深度转换对象到对象
+ * 2.封装Apache Commons BeanUtils, 将字符串转换为对象.
+ *
+ */
+public abstract class ObjectMapper {
+
+	/**
+	 * 持有Dozer单例, 避免重复创建DozerMapper消耗资源.
+	 */
+	private static DozerBeanMapper dozer = new DozerBeanMapper();
+
+	/**
+	 * 基于Dozer转换对象的类型.
+	 */
+	public static <T> T map(Object source, Class<T> destinationClass) {
+		return dozer.map(source, destinationClass);
+	}
+
+	/**
+	 * 基于Dozer转换Collection中对象的类型.
+	 */
+	public static <T> List<T> mapList(Collection sourceList, Class<T> destinationClass) {
+		List<T> destinationList = Lists.newArrayList();
+		for (Object sourceObject : sourceList) {
+			T destinationObject = dozer.map(sourceObject, destinationClass);
+			destinationList.add(destinationObject);
+		}
+		return destinationList;
+	}
+
+	static {
+		//初始化日期格式为yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss
+		registerDateConverter("yyyy-MM-dd,yyyy-MM-dd HH:mm:ss");
+	}
+
+	/**
+	 * 定义Apache BeanUtils日期Converter的格式,可注册多个格式,以','分隔
+	 */
+	public static void registerDateConverter(String patterns) {
+		DateConverter dc = new DateConverter();
+		dc.setUseLocaleFormat(true);
+		dc.setPatterns(StringUtils.split(patterns, ","));
+		ConvertUtils.register(dc, Date.class);
+	}
+
+	/**
+	 * 基于Apache BeanUtils转换字符串到相应类型.
+	 * 
+	 * @param value 待转换的字符串.
+	 * @param toType 转换目标类型.
+	 */
+	public static Object convertToObject(String value, Class<?> toType) {
+		Object cvt_value=null;
+		try {
+				cvt_value=ConvertUtils.convert(value, toType);	
+//			if(toType==Date.class){
+//				System.out.println("0----0");
+//				SimpleDateFormat dateFormat=null;
+//				try{
+//					dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//					cvt_value=dateFormat.parse(value);	
+//				}catch(Exception e){
+//					dateFormat=new SimpleDateFormat("yyyy-MM-dd");
+//					cvt_value=dateFormat.parse(value);	
+//				}
+//			}
+		} catch (Exception e) {
+			throw ReflectionUtils.convertReflectionExceptionToUnchecked(e);
+		}
+		return cvt_value;
+	}
+	
+}

+ 210 - 0
src/main/java/com/key/common/plugs/page/Page.java

@@ -0,0 +1,210 @@
+/**
+ * Copyright (c) 2005-2011 springside.org.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 
+ * $Id: Page.java 1547 2011-05-05 14:43:07Z calvinxiu $
+ */
+package com.key.common.plugs.page;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import com.google.common.collect.Lists;
+
+/**
+ * 与具体ORM实现无关的分页查询结果封装.
+ * 
+ * @param <T> Page中记录的类型.
+ *
+ */
+public class Page<T> extends PageRequest implements Iterable<T> {
+
+	protected List<T> result = null;
+	protected long totalItems = -1;
+	
+	public Page() {
+	}
+
+	public Page(PageRequest request) {
+		this.pageNo = request.pageNo;
+		this.pageSize = request.pageSize;
+		this.countTotal = request.countTotal;
+		this.orderBy = request.orderBy;
+		this.orderDir = request.orderDir;
+	}
+
+	/**
+	 * 获得页内的记录列表.
+	 */
+	public List<T> getResult() {
+		return result;
+	}
+
+	/**
+	 * 设置页内的记录列表.
+	 */
+	public void setResult(final List<T> result) {
+		this.result = result;
+	}
+
+	/**
+	 * 获得总记录数, 默认值为-1.
+	 */
+	public long getTotalItems() {
+		return totalItems;
+	}
+
+	/**
+	 * 设置总记录数.
+	 */
+	public void setTotalItems(final long totalItems) {
+		this.totalItems = totalItems;
+//		getSlider(this.pageNoSize);
+		setStartEndPageNo();
+	}
+
+	/** 
+	 * 实现Iterable接口, 可以for(Object item : page)遍历使用
+	 */
+	@Override
+	public Iterator<T> iterator() {
+		return result.iterator();
+	}
+
+	/**
+	 * 根据pageSize与totalItems计算总页数.
+	 */
+	public int getTotalPages() {
+		return (int) Math.ceil((double) totalItems / (double) getPageSize());
+
+	}
+
+	/**
+	 * 是否还有下一页.
+	 */
+	public boolean hasNextPage() {
+		return (getPageNo() + 1 <= getTotalPages());
+	}
+
+	/**
+	 * 是否最后一页.
+	 */
+	public boolean isLastPage() {
+		return !hasNextPage();
+	}
+
+	/**
+	 * 取得下页的页号, 序号从1开始.
+	 * 当前页为尾页时仍返回尾页序号.
+	 */
+	public int getNextPage() {
+		if (hasNextPage()) {
+			return getPageNo() + 1;
+		} else {
+			return getPageNo();
+		}
+	}
+
+	/**
+	 * 是否还有上一页.
+	 */
+	public boolean hasPrePage() {
+		return (getPageNo() > 1);
+	}
+
+	/**
+	 * 是否第一页.
+	 */
+	public boolean isFirstPage() {
+		return !hasPrePage();
+	}
+
+	/**
+	 * 取得上页的页号, 序号从1开始.
+	 * 当前页为首页时返回首页序号.
+	 */
+	public int getPrePage() {
+		if (hasPrePage()) {
+			return getPageNo() - 1;
+		} else {
+			return getPageNo();
+		}
+	}
+
+	/**
+	 * 计算以当前页为中心的页面列表,如"首页,23,24,25,26,27,末页"
+	 * @param count 需要计算的列表大小
+	 * @return pageNo列表 
+	 */
+	public List<Integer> getSlider(int count) {
+		int halfSize = count / 2;
+		totalPage = getTotalPages();
+
+		int startPageNo = Math.max(getPageNo() - halfSize, 1);
+		int endPageNo = Math.min(startPageNo + count - 1, totalPage);
+
+		if (endPageNo - startPageNo < count) {
+			startPageNo = Math.max(endPageNo - count, 1);
+		}
+
+		List<Integer> result = Lists.newArrayList();
+		for (int i = startPageNo; i <= endPageNo; i++) {
+			result.add(i);
+		}
+		this.pageNos=result;
+		return result;
+	}
+	
+	private int startpage;
+	private int endpage;
+	
+	public void setStartEndPageNo(){
+		totalPage = getTotalPages();
+		startpage = pageNo
+				- (pageNoSize % 2 == 0 ? pageNoSize / 2 - 1
+						: pageNoSize / 2);
+		endpage = pageNo + pageNoSize / 2;
+		if (startpage < 1) {
+			startpage = 1;
+			if (totalPage >= pageNoSize) {
+				endpage = pageNoSize;
+			} else {
+				endpage = totalPage;
+			}
+		}
+		if (endpage > totalPage) {
+			endpage = totalPage;
+			if ((endpage - pageNoSize) > 0) {
+				startpage = endpage - pageNoSize + 1;
+			} else {
+				startpage = 1;
+			}
+		}
+//		return new PageIndexUtil(startpage, endpage);
+	}
+	
+	public int getStartpage() {
+		return startpage;
+	}
+
+	public void setStartpage(int startpage) {
+		this.startpage = startpage;
+	}
+
+	public int getEndpage() {
+		return endpage;
+	}
+
+	public void setEndpage(int endpage) {
+		this.endpage = endpage;
+	}
+	
+	@Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this);
+	}
+	
+}

+ 215 - 0
src/main/java/com/key/common/plugs/page/PageRequest.java

@@ -0,0 +1,215 @@
+/**
+ * Copyright (c) 2005-2011 springside.org.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 
+ * $Id: Fixtures.java 1593 2011-05-11 10:37:12Z calvinxiu $
+ */
+package com.key.common.plugs.page;
+
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.google.common.collect.Lists;
+import com.key.common.utils.AssertUtils;
+
+/**
+ * 分页参数封装类.
+ */
+public class PageRequest {
+	protected int pageNo = 1;
+	protected int pageSize = 10;
+
+	protected String orderBy = null;
+	protected String orderDir = null;
+
+	protected boolean countTotal = true;
+
+	protected List<Integer> pageNos;
+	protected int pageNoSize = 5;
+
+	public PageRequest() {
+	}
+
+	public PageRequest(int pageNo, int pageSize) {
+		this.pageNo = pageNo;
+		this.pageSize = pageSize;
+	}
+
+	/**
+	 * 获得当前页的页号, 序号从1开始, 默认为1.
+	 */
+	public int getPageNo() {
+		return pageNo;
+	}
+
+	/**
+	 * 设置当前页的页号, 序号从1开始, 低于1时自动调整为1.
+	 */
+	public void setPageNo(final int pageNo) {
+		this.pageNo = pageNo;
+
+		if (pageNo < 1) {
+			this.pageNo = 1;
+		}
+	}
+
+	/**
+	 * 获得每页的记录数量, 默认为10.
+	 */
+	public int getPageSize() {
+		return pageSize;
+	}
+
+	/**
+	 * 设置每页的记录数量, 低于1时自动调整为1.
+	 */
+	public void setPageSize(final int pageSize) {
+		this.pageSize = pageSize;
+
+		if (pageSize < 1) {
+			this.pageSize = 1;
+		}
+	}
+
+	/**
+	 * 获得排序字段, 无默认值. 多个排序字段时用','分隔.
+	 */
+	public String getOrderBy() {
+		return orderBy;
+	}
+
+	/**
+	 * 设置排序字段, 多个排序字段时用','分隔.
+	 */
+	public void setOrderBy(final String orderBy) {
+		this.orderBy = orderBy;
+	}
+
+	/**
+	 * 获得排序方向, 无默认值.
+	 */
+	public String getOrderDir() {
+		return orderDir;
+	}
+
+	/**
+	 * 设置排序方式向.
+	 * 
+	 * @param orderDir
+	 *            可选值为desc或asc,多个排序字段时用','分隔.
+	 */
+	public void setOrderDir(final String orderDir) {
+		String lowcaseOrderDir = StringUtils.lowerCase(orderDir);
+
+		// 检查order字符串的合法值
+		String[] orderDirs = StringUtils.split(lowcaseOrderDir, ',');
+		for (String orderDirStr : orderDirs) {
+			if (!StringUtils.equals(Sort.DESC, orderDirStr)
+					&& !StringUtils.equals(Sort.ASC, orderDirStr)) {
+				throw new IllegalArgumentException("排序方向" + orderDirStr
+						+ "不是合法值");
+			}
+		}
+
+		this.orderDir = lowcaseOrderDir;
+	}
+
+	/**
+	 * 获得排序参数.
+	 */
+	public List<Sort> getSort() {
+		String[] orderBys = StringUtils.split(orderBy, ',');
+		String[] orderDirs = StringUtils.split(orderDir, ',');
+		AssertUtils.isTrue(orderBys.length == orderDirs.length,
+				"分页多重排序参数中,排序字段与排序方向的个数不相等");
+
+		List<Sort> orders = Lists.newArrayList();
+		for (int i = 0; i < orderBys.length; i++) {
+			orders.add(new Sort(orderBys[i], orderDirs[i]));
+		}
+
+		return orders;
+	}
+
+	/**
+	 * 是否已设置排序字段,无默认值.
+	 */
+	public boolean isOrderBySetted() {
+		return (StringUtils.isNotBlank(orderBy) && StringUtils
+				.isNotBlank(orderDir));
+	}
+
+	/**
+	 * 是否默认计算总记录数.
+	 */
+	public boolean isCountTotal() {
+		return countTotal;
+	}
+
+	/**
+	 * 设置是否默认计算总记录数.
+	 */
+	public void setCountTotal(boolean countTotal) {
+		this.countTotal = countTotal;
+	}
+
+	/**
+	 * 根据pageNo和pageSize计算当前页第一条记录在总结果集中的位置, 序号从0开始.
+	 */
+	public int getOffset() {
+		return ((pageNo - 1) * pageSize);
+	}
+
+	public static class Sort {
+		public static final String ASC = "asc";
+		public static final String DESC = "desc";
+
+		private final String property;
+		private final String dir;
+
+		public Sort(String property, String dir) {
+			this.property = property;
+			this.dir = dir;
+		}
+
+		public String getProperty() {
+			return property;
+		}
+
+		public String getDir() {
+			return dir;
+		}
+	}
+
+	public List<Integer> getPageNos() {
+		return pageNos;
+	}
+
+	public void setPageNoSize(int pageNoSize) {
+		this.pageNoSize = pageNoSize;
+	}
+
+	// 总页数
+	protected int totalPage;
+
+	public int getTotalPage() {
+		return totalPage;
+	}
+
+	public void setTotalPage(int totalPage) {
+		this.totalPage = totalPage;
+	}
+
+	// 是否取最后一页数据
+	private boolean islastpage=false;
+
+	public boolean isIslastpage() {
+		return islastpage;
+	}
+
+	public void setIslastpage(boolean islastpage) {
+		this.islastpage = islastpage;
+	}
+}

+ 170 - 0
src/main/java/com/key/common/plugs/page/PropertyFilter.java

@@ -0,0 +1,170 @@
+/**
+ * Copyright (c) 2005-2011 springside.org.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 
+ * $Id: PropertyFilter.java 1627 2011-05-23 16:23:18Z calvinxiu $
+ */
+package com.key.common.plugs.page;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.key.common.plugs.mapper.ObjectMapper;
+import com.key.common.utils.AssertUtils;
+import com.key.common.utils.web.ServletUtils;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * 与具体ORM实现无关的属性过滤条件封装类, 主要记录页面中简单的搜索过滤条件.
+ *
+ */
+public class PropertyFilter {
+
+	/** 多个属性间OR关系的分隔符. */
+	public static final String OR_SEPARATOR = "_OR_";
+
+	/** 属性比较类型. */
+	public enum MatchType {
+		EQ, LIKE, LT, GT, LE, GE, NE;
+	}
+
+	/** 属性数据类型. */
+	public enum PropertyType {
+		S(String.class), I(Integer.class), L(Long.class), N(Double.class), D(Date.class), B(Boolean.class);
+
+		private Class<?> clazz;
+
+		private PropertyType(Class<?> clazz) {
+			this.clazz = clazz;
+		}
+
+		public Class<?> getValue() {
+			return clazz;
+		}
+	}
+
+	private MatchType matchType = null;
+	private Object matchValue = null;
+
+	private Class<?> propertyClass = null;
+	private String[] propertyNames = null;
+
+	public PropertyFilter() {
+	}
+
+	/**
+	 * @param filterName 比较属性字符串,含待比较的比较类型、属性值类型及属性列表. 
+	 *                   eg. LIKES_NAME_OR_LOGIN_NAME
+	 * @param value 待比较的值.
+	 */
+	public PropertyFilter(final String filterName, final String value) {
+
+		String firstPart = StringUtils.substringBefore(filterName, "_");
+//		System.out.println("firstPart: "+firstPart);
+		String matchTypeCode = StringUtils.substring(firstPart, 0, firstPart.length() - 1);
+		String propertyTypeCode = StringUtils.substring(firstPart, firstPart.length() - 1, firstPart.length());
+
+		try {
+			matchType = Enum.valueOf(MatchType.class, matchTypeCode);
+		} catch (RuntimeException e) {
+			throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性比较类型.", e);
+		}
+
+		try {
+			propertyClass = Enum.valueOf(PropertyType.class, propertyTypeCode).getValue();
+		} catch (RuntimeException e) {
+			throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性值类型.", e);
+		}
+
+		String propertyNameStr = StringUtils.substringAfter(filterName, "_");
+		AssertUtils.isTrue(StringUtils.isNotBlank(propertyNameStr), "filter名称" + filterName + "没有按规则编写,无法得到属性名称.");
+		propertyNames = StringUtils.splitByWholeSeparator(propertyNameStr, PropertyFilter.OR_SEPARATOR);
+
+		this.matchValue = ObjectMapper.convertToObject(value, propertyClass);
+	}
+
+	/**
+	 * 从HttpRequest中创建PropertyFilter列表, 默认Filter属性名前缀为filter.
+	 * 
+	 * @see #buildFromHttpRequest(HttpServletRequest, String)
+	 */
+	public static List<PropertyFilter> buildFromHttpRequest(final HttpServletRequest request) {
+		return buildFromHttpRequest(request, "filter");
+	}
+
+	/**
+	 * 从HttpRequest中创建PropertyFilter列表
+	 * PropertyFilter命名规则为Filter属性前缀_比较类型属性类型_属性名.
+	 * 
+	 * eg.
+	 * filter_EQS_name
+	 * filter_LIKES_name_OR_email
+	 */
+	public static List<PropertyFilter> buildFromHttpRequest(final HttpServletRequest request, final String filterPrefix) {
+		List<PropertyFilter> filterList = new ArrayList<PropertyFilter>();
+
+		//从request中获取含属性前缀名的参数,构造去除前缀名后的参数Map.
+		Map<String, Object> filterParamMap = ServletUtils.getParametersStartingWith(request, filterPrefix + "_");
+
+		//分析参数Map,构造PropertyFilter列表
+		for (Map.Entry<String, Object> entry : filterParamMap.entrySet()) {
+			String filterName = entry.getKey();
+			String value = (String) entry.getValue();
+			//如果value值为空,则忽略此filter.
+			if (StringUtils.isNotBlank(value)) {
+				PropertyFilter filter = new PropertyFilter(filterName, value);
+				filterList.add(filter);
+			}
+		}
+
+		return filterList;
+	}
+
+	/**
+	 * 获取比较值的类型.
+	 */
+	public Class<?> getPropertyClass() {
+		return propertyClass;
+	}
+
+	/**
+	 * 获取比较方式.
+	 */
+	public MatchType getMatchType() {
+		return matchType;
+	}
+
+	/**
+	 * 获取比较值.
+	 */
+	public Object getMatchValue() {
+		return matchValue;
+	}
+
+	/**
+	 * 获取比较属性名称列表.
+	 */
+	public String[] getPropertyNames() {
+		return propertyNames;
+	}
+
+	/**
+	 * 获取唯一的比较属性名称.
+	 */
+	public String getPropertyName() {
+		AssertUtils.isTrue(propertyNames.length == 1, "There are not only one property in this filter.");
+		return propertyNames[0];
+	}
+
+	/**
+	 * 是否比较多个属性.
+	 */
+	public boolean hasMultiProperties() {
+		return (propertyNames.length > 1);
+	}
+}

+ 157 - 0
src/main/java/com/key/common/plugs/security/FormAuthenticationWithLockFilter.java

@@ -0,0 +1,157 @@
+package com.key.common.plugs.security;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import com.key.common.base.entity.User;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.ExcessiveAttemptsException;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.key.common.base.service.AccountManager;
+
+public class FormAuthenticationWithLockFilter extends FormAuthenticationFilter {
+	Log log=LogFactory.getLog(FormAuthenticationWithLockFilter.class);
+
+    private long  maxLoginAttempts = 10;
+
+    public static ConcurrentHashMap<String, AtomicLong> accountLockMap   = new ConcurrentHashMap<String, AtomicLong>();
+    
+    private String successAdminUrl;
+  
+    private String successAdminRole;
+    
+    
+    @Autowired
+    protected AccountManager accountManager;
+    
+    @Override
+    public boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
+        AuthenticationToken token = createToken(request, response);
+        if (token == null) {
+            String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken "
+                    + "must be created in order to execute a login attempt.";
+            throw new IllegalStateException(msg);
+        }
+        if (checkIfAccountLocked(request)) {
+            return onLoginFailure(token, new ExcessiveAttemptsException(), request, response);
+        } else {
+            if (!doLogin(request, response, token)) {
+                resetAccountLock(getUsername(request));
+                return false;
+            }
+            return true;
+        }
+    }
+
+    public boolean checkIfAccountLocked(ServletRequest request) {
+        String username = getUsername(request);
+        if (username!=null && accountLockMap.get((String) username) != null) {
+            long remainLoginAttempts = accountLockMap.get((String) username).get();
+            if (remainLoginAttempts <= 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    
+    private boolean doLogin(ServletRequest request, ServletResponse response, AuthenticationToken token)
+            throws Exception {
+        try {
+            Subject subject = getSubject(request, response);
+            subject.login(token);
+            
+//    		User user = accountManager.findUserByLoginName(getUsername(request));
+    		User user = accountManager.findUserByLoginNameOrEmail(getUsername(request));
+
+            return onLoginSuccess(token, subject, request, response);
+        } catch (IncorrectCredentialsException e) {
+            decreaseAccountLoginAttempts(request);
+            checkIfAccountLocked(request);
+            return onLoginFailure(token, e, request, response);
+        } catch (AuthenticationException e) {
+            return onLoginFailure(token, e, request, response);
+        }
+    }
+
+    public void decreaseAccountLoginAttempts(ServletRequest request) {
+        AtomicLong initValue = new AtomicLong(maxLoginAttempts);
+        AtomicLong remainLoginAttempts = accountLockMap.putIfAbsent(getUsername(request), new AtomicLong(maxLoginAttempts));
+        if (remainLoginAttempts == null) {
+            remainLoginAttempts = initValue;
+        }
+        remainLoginAttempts.getAndDecrement();
+        accountLockMap.put(getUsername(request), remainLoginAttempts);
+    }
+
+    public void resetAccountLock(String username) {
+        accountLockMap.put(username, new AtomicLong(maxLoginAttempts));
+    }
+
+    public void setMaxLoginAttempts(long maxLoginAttempts) {
+        this.maxLoginAttempts = maxLoginAttempts;
+    }
+    
+    public void setSuccessAdminUrl(String successAdminUrl) {
+		this.successAdminUrl = successAdminUrl;
+	}
+    
+    public void setSuccessAdminRole(String successAdminRole) {
+		this.successAdminRole = successAdminRole;
+	}
+    
+    /* 得到某个账号还可以登录次数 */
+    public Long getAccountLocked(String username){
+   	 long remainLoginAttempts=0;
+        if (username!=null && accountLockMap.get((String) username) != null) {
+            remainLoginAttempts = accountLockMap.get((String) username).get();
+        }
+        return remainLoginAttempts+1;
+   }
+    /* 重写登录失败,加入了失败时还可以重试的次数信息 */
+    @Override
+    protected boolean onLoginFailure(AuthenticationToken token,
+    		AuthenticationException e, ServletRequest request,
+    		ServletResponse response) {
+    	request.setAttribute("remainLoginAttempt", getAccountLocked(getUsername(request)));
+    	return super.onLoginFailure(token, e, request, response);
+    }
+    
+    
+    @Override
+    protected String getUsername(ServletRequest request) {
+    	// TODO Auto-generated method stub
+    	String username = super.getUsername(request);
+    	if(username==null){
+    		Object temp=request.getAttribute(getUsernameParam());
+    		username=temp!=null?temp.toString():null;
+    	}
+    	return username;
+    }
+    @Override
+    protected String getPassword(ServletRequest request) {
+    	String password = super.getPassword(request);
+    	if(password==null){
+    		Object temp=request.getAttribute(getPasswordParam());
+    		password=temp!=null?temp.toString():null;
+    	}
+    	return password;
+    }
+    
+    @Override
+    protected boolean isRememberMe(ServletRequest request) {
+//    	 TODO Auto-generated method stub
+    	return super.isRememberMe(request);
+    }
+
+}

+ 130 - 0
src/main/java/com/key/common/plugs/security/LoginAction.java

@@ -0,0 +1,130 @@
+/*
+ * $HeadURL: $
+ * $Id: $
+ * Copyright (c) 2011 by Ericsson, all rights reserved.
+ */
+
+package com.key.common.plugs.security;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.key.common.base.entity.User;
+import com.key.common.base.service.AccountManager;
+import com.key.common.utils.web.Struts2Utils;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.subject.Subject;
+import org.apache.struts2.convention.annotation.AllowedMethods;
+import org.apache.struts2.convention.annotation.Namespace;
+import org.apache.struts2.convention.annotation.Result;
+import org.apache.struts2.convention.annotation.Results;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * @author keyuan(keyuan258@gmail.com)
+ *
+ * https://github.com/wkeyuan/DWSurvey
+ * http://dwsurvey.net
+ */
+@Namespace("/")
+@Results({
+	@Result(name = "index", location = "index.jsp", type = "redirect"),
+	@Result(name = "login", location = "login.jsp", type = "redirect")
+	})
+@AllowedMethods({"login","logout"})
+public class LoginAction extends ActionSupport {
+
+	private static final long serialVersionUID = 7392913081177740732L;
+	@Autowired
+	private FormAuthenticationWithLockFilter formAuthFilter;
+	@Autowired
+	protected AccountManager accountManager;
+	
+	public String login() throws Exception {
+		
+		System.out.println("username1-1");
+		HttpServletRequest request = Struts2Utils.getRequest();
+		HttpServletResponse response = Struts2Utils.getResponse();
+		
+		Subject subject = SecurityUtils.getSubject();
+		boolean isAuth = subject.isAuthenticated();
+		// 返回成功与否
+		String error="";
+		Long resetnum=0L;
+		if (!isAuth) {
+			String username = request.getParameter("username");
+			String password = request.getParameter("password");
+//			System.out.println(username+" "+password);
+			UsernamePasswordToken token = new UsernamePasswordToken(username,
+					password);
+			if(!formAuthFilter.checkIfAccountLocked(request)){
+				try {
+					subject.login(token);
+					formAuthFilter.resetAccountLock(username);
+					isAuth = true;
+				}catch (IncorrectCredentialsException e) {
+					formAuthFilter.decreaseAccountLoginAttempts(request);
+		            isAuth = false;
+		            error="IncorrectCredentialsException";
+		            resetnum=formAuthFilter.getAccountLocked(username);
+		        } catch (AuthenticationException e) {
+		            isAuth = false;
+		            error="AuthenticationException";
+		        }
+			}else{
+				//ExcessiveAttemptsException超过登录次数
+				 error="ExcessiveAttemptsException";
+			}
+		}
+		//PrintWriter writer = response.getWriter();    
+		//writer.write(isAuth + ","+error);//此种方式,在$.getJson()进行仿问时会出现不执行回调函数
+//		System.out.println(isAuth+","+error);
+		response.setContentType("text/plain");// 1.设置返回响应的类型
+		//2. 01 一定要注意:要包括jsoncallback参数,不然回调函数不执行。
+		//2. 02 返回的数据一定要是严格符合json格式 ,不然回调函数不执行。
+        response.getWriter().write( request.getParameter("jsoncallback") + "({isAuth:'"+isAuth+"',error:'"+error+"',resetnum:'"+resetnum+"'})" );
+		return null;
+		// 跳转到成功页面
+	}
+
+	public String logout() throws Exception {
+		System.out.println("............logout..................");
+		if (SecurityUtils.getSubject() != null) {
+			SecurityUtils.getSubject().logout();
+		}
+		Struts2Utils.getSession().invalidate();
+		return "index";
+	}
+	/* 给某个锁定的账号开锁,管理员使用 */
+	
+	public String lockout() throws Exception {
+		HttpServletRequest request=Struts2Utils.getRequest();
+		HttpServletResponse response=Struts2Utils.getResponse();
+		String username=request.getParameter("username");
+		//确认有没账号
+		boolean isup=false;
+		String error="用户不存在";
+		
+		if(username!=null){
+//			User user=accountManager.findUserByLoginName(username);
+			User user = accountManager.findUserByLoginNameOrEmail(username);
+			if(user!=null){
+				formAuthFilter.resetAccountLock(username);
+				isup=true;
+			}
+		}
+		response.getWriter().write(isup?username+"解锁成功":username+","+error);
+		return null;
+	}
+	
+	public String register() throws Exception {
+		
+		return "";
+	}
+
+}

+ 21 - 0
src/main/java/com/key/common/plugs/security/MyDefaultWebSecurityManager.java

@@ -0,0 +1,21 @@
+package com.key.common.plugs.security;
+
+import com.key.common.base.entity.User;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.key.common.base.service.AccountManager;
+
+public class MyDefaultWebSecurityManager extends DefaultWebSecurityManager{
+	@Autowired
+	private AccountManager accountManager;
+	
+	public String getUserId(){
+		User user=accountManager.getCurUser();
+		if(user!=null){
+			return user.getId();
+		}
+		return null;
+	}
+	
+}

+ 100 - 0
src/main/java/com/key/common/plugs/security/ShiroDbRealm.java

@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.key.common.plugs.security;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.key.common.base.entity.User;
+import com.key.common.base.service.AccountManager;
+import com.key.common.utils.security.DigestUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.subject.SimplePrincipalCollection;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.key.common.utils.web.Struts2Utils;
+
+public class ShiroDbRealm extends AuthorizingRealm {
+
+	@Autowired
+	protected AccountManager accountManager;
+
+	public ShiroDbRealm() {
+		setCredentialsMatcher(new HashedCredentialsMatcher("SHA-1"));
+	}
+
+	/**
+	 * 认证回调函数,登录时调用.
+	 */
+	@Override
+	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
+		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
+//		User user = accountManager.findUserByLoginName(token.getUsername());
+		
+		//根据loginToken 看能不查到当前token token有效期就1分钟
+		
+		String tokenPassword=new String(token.getPassword());
+
+		User user = accountManager.findUserByLoginNameOrEmail(token.getUsername());
+
+		//user.getStandardLock()==1 
+		if (user != null &&  user.getStatus().intValue()!=0 && !user.getLoginName().endsWith("@chacuo.net")) {
+			 return new SimpleAuthenticationInfo(user.getLoginName(), user.getShaPassword() , getName());
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
+	 */
+	@Override
+	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+		String username = (String) principals.fromRealm(getName()).iterator().next();
+//		User user = accountManager.findUserByLoginName(username);
+		User user = accountManager.findUserByLoginNameOrEmail(username);
+		if (user != null) {
+			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
+			return info;
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * 更新用户授权信息缓存.
+	 */
+	public void clearCachedAuthorizationInfo(String principal) {
+		SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
+		clearCachedAuthorizationInfo(principals);
+	}
+	
+}

+ 29 - 0
src/main/java/com/key/common/plugs/spss/demo/CSVExportUtil.java

@@ -0,0 +1,29 @@
+package com.key.common.plugs.spss.demo;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+
+import com.pmstation.spss.SPSSWriter;
+
+public class CSVExportUtil {
+	
+	private String xlsFileName;
+	private String path;
+	private  OutputStream out;
+	private  SPSSWriter outSPSS;
+	
+	public CSVExportUtil(String fileName,String path) {
+		try {
+			this.xlsFileName = fileName;
+			this.path=path;
+			this.out= new FileOutputStream(path+fileName);
+			outSPSS = new SPSSWriter(out, "windows-1252");
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		}
+	}
+	
+}

+ 33 - 0
src/main/java/com/key/common/plugs/spss/demo/csv/DemoCsv.java

@@ -0,0 +1,33 @@
+package com.key.common.plugs.spss.demo.csv;
+
+import java.io.*;
+import com.pmstation.spss.*;
+
+public class DemoCsv {
+  public static void main(String[] args){
+    // Parse the command line
+    if (args.length != 2) {
+        printUsageAndExit();
+    }
+
+    // Create files from 2 command line parameters
+    File fileCSV = new File(args[0]);
+    File fileSPSS = new File(args[1]);
+
+    // Do convert from CSV to SPSS format
+    try {
+      CsvToSPSS.convert(fileCSV, fileSPSS, null);
+    } catch (Exception e){
+      e.printStackTrace();
+    }
+  }
+  
+  private static void printUsageAndExit() {
+    System.err.println("Usage:");
+    System.err.println("java " +
+        DemoCsv.class.getName() +
+        " <fileCSV> <fileSPSS>");
+
+    System.exit(1);
+  }
+}

+ 7 - 0
src/main/java/com/key/common/plugs/spss/demo/csv/demo.csv

@@ -0,0 +1,7 @@
+Asia,44579000,3674000000,44
+Africa,30065000,778000000,53
+North America,24256000,483000000,23
+South America,17819000,342000000,12
+Antarctica,13209000,0,0
+Europe,9938000,732000000,46
+Australia/Oceania,7687000,31000000,14

+ 113 - 0
src/main/java/com/key/common/plugs/spss/demo/java/Demo.java

@@ -0,0 +1,113 @@
+package com.key.common.plugs.spss.demo.java;
+
+import java.io.*;
+import com.pmstation.spss.*;
+
+public class Demo {
+
+  // Entrance point
+  public static void main(String args[]) {
+    try {
+    	String fileName="F:\\source code\\spss\\spssw-1.66\\spss\\test.csv";
+      // Parse the command line
+//      if (args.length != 1) {
+//          printUsageAndExit();
+//      }
+
+      // Open file output stream with filename args[0]
+      OutputStream out = new FileOutputStream(fileName);
+
+      // Assign SPSS output to the file
+      SPSSWriter outSPSS = new SPSSWriter(out, "gbk");
+
+      // Creating SPSS variable description table
+      outSPSS.setCalculateNumberOfCases(false);
+      outSPSS.addDictionarySection(-1);
+
+      // Describing varible names and types
+      outSPSS.addStringVar("cont", 32, "continents of the world");
+      outSPSS.addNumericVar("size", 8, 2, "sq km");
+      outSPSS.addNumericVar("pop", 8, 2, "population");
+
+      // Create missing value 
+      MissingValue mv = new MissingValue();
+      mv.setOneDescreteMissingValue(1);
+      outSPSS.addNumericVar("count", 8, 2, "number of countries", mv);
+
+      // Create value labels
+      ValueLabels valueLabels = new ValueLabels();
+      valueLabels.putLabel(44, "Forty four");
+      valueLabels.putLabel(23, "Twenty three");
+      outSPSS.addValueLabels(4 , valueLabels);
+
+      // Create SPSS varible value define table
+      outSPSS.addDataSection();
+
+      // Add values for all defined variables
+      outSPSS.addData("Asia");
+      outSPSS.addData(new Long(44579000L));
+      outSPSS.addData(new Long(3674000000L));
+      outSPSS.addData(new Long(44));
+
+      outSPSS.addData("Africa");
+      outSPSS.addData(new Long(30065000L));
+      outSPSS.addData(new Long(778000000L));
+      outSPSS.addData(new Long(53));
+
+      outSPSS.addData("North America");
+      outSPSS.addData(new Long(24256000L));
+      outSPSS.addData(new Long(483000000L));
+      outSPSS.addData(new Long(23));
+
+      outSPSS.addData("South America");
+      outSPSS.addData(new Long(17819000L));
+      outSPSS.addData(new Long(342000000L));
+      outSPSS.addData(new Long(12));
+
+      outSPSS.addData("Antarctica");
+      outSPSS.addData(new Long(13209000L));
+      outSPSS.addData(new Long(0));
+      outSPSS.addData(new Long(0));
+
+      outSPSS.addData("Europe");
+      outSPSS.addData(new Long(9938000L));
+      outSPSS.addData(new Long(732000000L));
+      outSPSS.addData(new Long(46));
+
+      outSPSS.addData("Australia/Oceania");
+      outSPSS.addData(new Long(7687000L));
+      outSPSS.addData(new Long(31000000L));
+      outSPSS.addData(new Long(14));
+
+      outSPSS.addData("Transelvania");
+      outSPSS.addData(new Long(7345560L));
+      outSPSS.addData(new Long(34565456L));
+      outSPSS.addData(new Long(44));
+
+      // Create SPSS ending section
+      outSPSS.addFinishSection();
+
+      // Close output stream
+      out.close();
+    }
+    catch (FileNotFoundException exOb) {
+      System.out.println("FileNotFoundException (Demo.main): " +
+          exOb.getMessage());
+      exOb.printStackTrace(System.out);
+      return;
+    }
+    catch (IOException exOb) {
+      System.out.println("IOException (Demo.main): " + exOb.getMessage());
+      exOb.printStackTrace(System.out);
+      return;
+    }
+  }
+
+  private static void printUsageAndExit() {
+    System.err.println("Usage:");
+    System.err.println("java " +
+        Demo.class.getName() +
+        " <fileSPSS>");
+    System.exit(1);
+  }
+}

+ 34 - 0
src/main/java/com/key/common/plugs/spss/demo/xml/DemoXml.java

@@ -0,0 +1,34 @@
+package com.key.common.plugs.spss.demo.xml;
+
+import java.io.*;
+
+import com.key.common.plugs.spss.demo.csv.DemoCsv;
+import com.pmstation.spss.*;
+
+public class DemoXml {
+  public static void main(String[] args){
+    // Parse the command line
+    if (args.length != 2) {
+        printUsageAndExit();
+    }
+
+    // Create files from 2 command line parameters
+    File fileXml = new File(args[0]);
+    File fileSPSS = new File(args[1]);
+
+    // Do convert from XML to SPSS format
+    try {
+      XmlToSPSS.convert(fileXml, fileSPSS, null);
+    } catch (Exception e){
+      e.printStackTrace();
+    }
+  }
+
+  private static void printUsageAndExit() {
+    System.err.println("Usage:");
+    System.err.println("java " + DemoCsv.class.getName() +
+        " <fileXML> <fileSPSS>");
+
+    System.exit(1);
+  }
+}

+ 59 - 0
src/main/java/com/key/common/plugs/spss/demo/xml/demo.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<spssfile>
+    <variable>
+        <string name="cont" length="32" label="continents of the world" />
+        <numeric name="size" width="8" decimals="2" label="sq km" />
+        <numeric name="pop" width="8" decimals="2" label="population" />
+        <numeric name="count" width="8" decimals="2" label="number of countries" />
+    </variable>
+    <valueLabels varnum="4">
+      <lable name="Forty four" value="44" />
+      <lable name="Twenty three" value="23" />
+    </valueLabels>
+
+    <data>
+        <row>
+            <value>Asia</value>
+            <value>44579000</value>
+            <value>3674000000</value>
+            <value>44</value>
+        </row>
+        <row>
+            <value>Africa</value>
+            <value>30065000</value>
+            <value>778000000</value>
+            <value>53</value>
+        </row>
+        <row>
+            <value>North America</value>
+            <value>24256000</value>
+            <value>483000000</value>
+            <value>23</value>
+        </row>
+        <row>
+            <value>South America</value>
+            <value>17819000</value>
+            <value>342000000</value>
+            <value>12</value>
+        </row>
+        <row>
+            <value>Antarctica</value>
+            <value>13209000</value>
+            <value>0</value>
+            <value>0</value>
+        </row>
+        <row>
+            <value>Europe</value>
+            <value>9938000</value>
+            <value>732000000</value>
+            <value>46</value>
+        </row>
+        <row>
+            <value>Australia/Oceania</value>
+            <value>7687000</value>
+            <value>31000000</value>
+            <value>14</value>
+        </row>
+
+    </data>
+</spssfile>

+ 39 - 0
src/main/java/com/key/common/plugs/xss/XssFilter.java

@@ -0,0 +1,39 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.key.common.plugs.xss;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Xss保护过滤器
+ *
+ * @author storezhang
+ */
+public class XssFilter implements Filter {
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        System.out.println("Xss filter inited!");
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        XssHttpWrapper xssRequest = new XssHttpWrapper((HttpServletRequest) request);
+        chain.doFilter(xssRequest, response);
+    }
+
+    @Override
+    public void destroy() {
+        System.out.println("Xss filter destroyed!");
+    }
+}

+ 143 - 0
src/main/java/com/key/common/plugs/xss/XssHttpWrapper.java

@@ -0,0 +1,143 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.key.common.plugs.xss;
+
+import com.blogspot.radialmind.html.HTMLParser;
+import com.blogspot.radialmind.xss.XSSFilter;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+/**
+ * XSS保护
+ *
+ * @author storezhang
+ */
+public class XssHttpWrapper extends HttpServletRequestWrapper {
+
+    private HttpServletRequest orgRequest;
+
+    public XssHttpWrapper(HttpServletRequest request) {
+        super(request);
+        orgRequest = request;
+    }
+
+    /**
+     * 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/>
+     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
+     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
+     */
+    @Override
+    public String getParameter(String name) {
+        String value = super.getParameter(xssEncode(name));
+        if (value != null) {
+            value = xssEncode(value);
+        }
+        return value;
+    }
+    
+    /**
+     * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/>
+     * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/> getHeaderNames 也可能需要覆盖
+     */
+    @Override
+    public String getHeader(String name) {
+        String value = super.getHeader(xssEncode(name));
+        if (value != null) {
+            value = xssEncode(value);
+        }
+        return value;
+    }
+
+    
+    
+    /**
+    *
+    * @param name
+    * @return
+    */
+   public String[] getParameterValues(String name) {
+       String[] values = super.getParameterValues(name);
+       if (values != null) {
+           for (int i = 0; i < values.length; i++) {
+               values[i] = xssEncode(values[i]);
+           }
+       }
+       return values;
+   }
+
+   /**
+    * @return
+    */
+   public Map getParameterMap() {
+
+       HashMap paramMap = (HashMap) super.getParameterMap();
+       paramMap = (HashMap) paramMap.clone();
+
+       for (Iterator iterator = paramMap.entrySet().iterator(); iterator.hasNext(); ) {
+           Map.Entry entry = (Map.Entry) iterator.next();
+           String[] values = (String[]) entry.getValue();
+           for (int i = 0; i < values.length; i++) {
+               if(values[i] instanceof String){
+                   values[i] = xssEncode((String)values[i]);
+               }
+           }
+           entry.setValue(values);
+       }
+       return paramMap;
+   }
+    
+    
+    /**
+     * 将容易引起xss漏洞的半角字符直接替换成全角字符
+     *
+     * @param s
+     * @return
+     */
+    private static String xssEncode(String s) {
+        if (s == null || s.isEmpty()) {
+            return s;
+        }
+
+        StringReader reader = new StringReader(s);
+        StringWriter writer = new StringWriter();
+        try {
+            HTMLParser.process(reader, writer, new XSSFilter(), true);
+            return writer.toString();
+        } catch (NullPointerException e) {
+            return s;
+        } catch (Exception ex) {
+            ex.printStackTrace(System.out);
+        }
+        return null;
+    }
+
+    /**
+     * 获取最原始的request
+     *
+     * @return
+     */
+    public HttpServletRequest getOrgRequest() {
+        return orgRequest;
+    }
+
+    /**
+     * 获取最原始的request的静态方法
+     *
+     * @return
+     */
+    public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
+        if (req instanceof XssHttpWrapper) {
+            return ((XssHttpWrapper) req).getOrgRequest();
+        }
+        return req;
+    }
+}

+ 35 - 0
src/main/java/com/key/common/service/BaseService.java

@@ -0,0 +1,35 @@
+package com.key.common.service;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.hibernate.criterion.Criterion;
+
+import com.key.common.base.entity.IdEntity;
+import com.key.common.plugs.page.Page;
+import com.key.common.plugs.page.PropertyFilter;
+
+public interface BaseService<T extends IdEntity,ID extends Serializable> {
+	
+	public void setBaseDao();
+	
+	public void save(T t);
+	
+	public void delete(T t);
+	
+	public void delete(ID id);
+	
+	public T get(ID id);
+	
+	public T getModel(ID id);
+	
+	public Page<T> findPage(Page<T> page,List<PropertyFilter> filters);
+	
+	public List<T> findList(List<PropertyFilter> filters);
+	
+	public List<T> findAll(Page<T> page,List<PropertyFilter> filters);
+
+	public List<T> findList(Criterion... criterions);
+	
+	public Page<T> findPage(Page<T> page,Criterion... criterion);
+}

+ 76 - 0
src/main/java/com/key/common/service/BaseServiceImpl.java

@@ -0,0 +1,76 @@
+package com.key.common.service;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.hibernate.criterion.Criterion;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.key.common.base.entity.IdEntity;
+import com.key.common.dao.BaseDao;
+import com.key.common.plugs.page.Page;
+import com.key.common.plugs.page.PropertyFilter;
+
+@Transactional
+public abstract class BaseServiceImpl<T extends IdEntity, ID extends Serializable>
+		implements BaseService<T, ID> {
+
+	protected BaseDao<T, ID> baseDao;
+	
+	protected BaseDao<T, ID> getBaseDao() {
+		if (baseDao == null) {
+			setBaseDao();
+		}
+		return baseDao;
+	}
+
+	@Override
+	public void save(T t) {
+		String id = t.getId();
+		if (id != null && "".equals(id)) {
+			t.setId(null);
+		}
+		getBaseDao().save(t);
+	}
+
+	@Override
+	public void delete(T t) {
+		getBaseDao().delete(t);
+	}
+
+	public void delete(ID id) {
+		getBaseDao().delete(get(id));
+	};
+	
+	public T get(ID id) {
+		return getBaseDao().get(id);
+	}
+
+	public T getModel(ID id) {
+		return getBaseDao().getModel(id);
+	};
+
+	public Page<T> findPage(Page<T> page, List<PropertyFilter> filters) {
+		return getBaseDao().findPage(page, filters);
+	}
+
+	@Override
+	public List<T> findList(List<PropertyFilter> filters) {
+		return getBaseDao().find(filters);
+	}
+	
+	@Override
+	public List<T> findAll(Page<T> page, List<PropertyFilter> filters) {
+		return getBaseDao().findAll(page, filters);
+	}
+	
+	@Override
+	public List<T> findList(Criterion... criterions) {
+		return getBaseDao().find(criterions);
+	}
+	
+	@Override
+	public Page<T> findPage(Page<T> page, Criterion... criterions) {
+		return getBaseDao().findPage(page, criterions);
+	}
+}

+ 441 - 0
src/main/java/com/key/common/utils/AssertUtils.java

@@ -0,0 +1,441 @@
+/**
+ * Copyright (c) 2005-2011 springside.org.cn
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 
+ * $Id: Fixtures.java 1593 2011-05-11 10:37:12Z calvinxiu $
+ */
+package com.key.common.utils;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * 与Spring Assert功能类似, 代码基本从org.springframework.util.Assert复制, 增加如下功能:
+ * 
+ * 1. 修改类名, 免得一天到晚和org.junit.Assert冲突.
+ * 2. 可抛出指定的业务异常类, 而不是通用的IllegalArgumentException.
+ * 
+ * 代码示例:
+ * <pre class="code">AssertUtils.hasText(uName, new IllegalBizArgumentsException(ErrorCode.USERNAME_ERROR));</pre>
+ *   
+ * @author badqiu
+ */
+public abstract class AssertUtils {
+
+	/**
+	 * Assert a boolean expression, throwing <code>IllegalArgumentException</code>
+	 * if the test result is <code>false</code>.
+	 * <pre class="code">Assert.isTrue(i &gt; 0);</pre>
+	 * @param expression a boolean expression
+	 * @throws IllegalArgumentException if expression is <code>false</code>
+	 */
+	public static void isTrue(boolean expression) {
+		isTrue(expression, "[Assertion failed] - this expression must be true");
+	}
+
+	/**
+	 * Assert a boolean expression, throwing <code>IllegalArgumentException</code>
+	 * if the test result is <code>false</code>.
+	 * <pre class="code">Assert.isTrue(i &gt; 0, "The value must be greater than zero");</pre>
+	 * @param expression a boolean expression
+	 * @param message the exception message to use if the assertion fails
+	 * @throws IllegalArgumentException if expression is <code>false</code>
+	 */
+	public static void isTrue(boolean expression, String message) {
+		if (!expression) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	public static void isTrue(boolean expression, RuntimeException throwIfAssertFail) {
+		if (!expression) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that an object is <code>null</code> .
+	 * <pre class="code">Assert.isNull(value);</pre>
+	 * @param object the object to check
+	 * @throws IllegalArgumentException if the object is not <code>null</code>
+	 */
+	public static void isNull(Object object) {
+		isNull(object, "[Assertion failed] - the object argument must be null");
+	}
+
+	/**
+	 * Assert that an object is <code>null</code> .
+	 * <pre class="code">Assert.isNull(value, "The value must be null");</pre>
+	 * @param object the object to check
+	 * @param message the exception message to use if the assertion fails
+	 * @throws IllegalArgumentException if the object is not <code>null</code>
+	 */
+	public static void isNull(Object object, String message) {
+		if (object != null) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	public static void isNull(Object object, RuntimeException throwIfAssertFail) {
+		if (object != null) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that an object is not <code>null</code> .
+	 * <pre class="code">Assert.notNull(clazz);</pre>
+	 * @param object the object to check
+	 * @throws IllegalArgumentException if the object is <code>null</code>
+	 */
+	public static void notNull(Object object) {
+		notNull(object, "[Assertion failed] - this argument is required; it must not be null");
+	}
+
+	/**
+	 * Assert that an object is not <code>null</code> .
+	 * <pre class="code">Assert.notNull(clazz, "The class must not be null");</pre>
+	 * @param object the object to check
+	 * @param message the exception message to use if the assertion fails
+	 * @throws IllegalArgumentException if the object is <code>null</code>
+	 */
+	public static void notNull(Object object, String message) {
+		if (object == null) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	public static void notNull(Object object, RuntimeException throwIfAssertFail) {
+		if (object == null) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that the given String is not empty; that is,
+	 * it must not be <code>null</code> and not the empty String.
+	 * <pre class="code">Assert.hasLength(name);</pre>
+	 * @param text the String to check
+	 * @see StringUtils#hasLength
+	 */
+	public static void hasLength(String text) {
+		hasLength(text, "[Assertion failed] - this String argument must have length; it must not be null or empty");
+	}
+
+	/**
+	 * Assert that the given String is not empty; that is,
+	 * it must not be <code>null</code> and not the empty String.
+	 * <pre class="code">Assert.hasLength(name, "Name must not be empty");</pre>
+	 * @param text the String to check
+	 * @param message the exception message to use if the assertion fails
+	 * @see StringUtils#hasLength
+	 */
+	public static void hasLength(String text, String message) {
+		if (!StringUtils.hasLength(text)) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	public static void hasLength(String text, RuntimeException throwIfAssertFail) {
+		if (!StringUtils.hasLength(text)) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that the given String has valid text content; that is, it must not
+	 * be <code>null</code> and must contain at least one non-whitespace character.
+	 * <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre>
+	 * @param text the String to check
+	 * @see StringUtils#hasText
+	 */
+	public static void hasText(String text) {
+		hasText(text, "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank");
+	}
+
+	/**
+	 * Assert that the given String has valid text content; that is, it must not
+	 * be <code>null</code> and must contain at least one non-whitespace character.
+	 * <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre>
+	 * @param text the String to check
+	 * @param message the exception message to use if the assertion fails
+	 * @see StringUtils#hasText
+	 */
+	public static void hasText(String text, String message) {
+		if (!StringUtils.hasText(text)) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	public static void hasText(String text, RuntimeException throwIfAssertFail) {
+		if (!StringUtils.hasText(text)) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that the given text does not contain the given substring.
+	 * <pre class="code">Assert.doesNotContain(name, "rod");</pre>
+	 * @param textToSearch the text to search
+	 * @param substring the substring to find within the text
+	 */
+	public static void doesNotContain(String textToSearch, String substring) {
+		doesNotContain(textToSearch, substring,
+				"[Assertion failed] - this String argument must not contain the substring [" + substring + "]");
+	}
+
+	/**
+	 * Assert that the given text does not contain the given substring.
+	 * <pre class="code">Assert.doesNotContain(name, "rod", "Name must not contain 'rod'");</pre>
+	 * @param textToSearch the text to search
+	 * @param substring the substring to find within the text
+	 * @param message the exception message to use if the assertion fails
+	 */
+	public static void doesNotContain(String textToSearch, String substring, String message) {
+		if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring)
+				&& textToSearch.indexOf(substring) != -1) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	public static void doesNotContain(String textToSearch, String substring, RuntimeException throwIfAssertFail) {
+		if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring)
+				&& textToSearch.indexOf(substring) != -1) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that an array has elements; that is, it must not be
+	 * <code>null</code> and must have at least one element.
+	 * <pre class="code">Assert.notEmpty(array);</pre>
+	 * @param array the array to check
+	 * @throws IllegalArgumentException if the object array is <code>null</code> or has no elements
+	 */
+	public static void notEmpty(Object[] array) {
+		notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element");
+	}
+
+	/**
+	 * Assert that an array has elements; that is, it must not be
+	 * <code>null</code> and must have at least one element.
+	 * <pre class="code">Assert.notEmpty(array, "The array must have elements");</pre>
+	 * @param array the array to check
+	 * @param message the exception message to use if the assertion fails
+	 * @throws IllegalArgumentException if the object array is <code>null</code> or has no elements
+	 */
+	public static void notEmpty(Object[] array, String message) {
+		if (ObjectUtils.isEmpty(array)) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	public static void notEmpty(Object[] array, RuntimeException throwIfAssertFail) {
+		if (ObjectUtils.isEmpty(array)) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that an array has no null elements.
+	 * Note: Does not complain if the array is empty!
+	 * <pre class="code">Assert.noNullElements(array, "The array must have non-null elements");</pre>
+	 * @param array the array to check
+	 * @param message the exception message to use if the assertion fails
+	 * @throws IllegalArgumentException if the object array contains a <code>null</code> element
+	 */
+	public static void noNullElements(Object[] array, String message) {
+		if (array != null) {
+			for (Object element : array) {
+				if (element == null) {
+					throw new IllegalArgumentException(message);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Assert that an array has no null elements.
+	 * Note: Does not complain if the array is empty!
+	 * <pre class="code">Assert.noNullElements(array);</pre>
+	 * @param array the array to check
+	 * @throws IllegalArgumentException if the object array contains a <code>null</code> element
+	 */
+	public static void noNullElements(Object[] array) {
+		noNullElements(array, "[Assertion failed] - this array must not contain any null elements");
+	}
+
+	public static void noNullElements(Object[] array, RuntimeException throwIfAssertFail) {
+		if (array != null) {
+			for (Object element : array) {
+				if (element == null) {
+					throw throwIfAssertFail;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Assert that a collection has elements; that is, it must not be
+	 * <code>null</code> and must have at least one element.
+	 * <pre class="code">Assert.notEmpty(collection, "Collection must have elements");</pre>
+	 * @param collection the collection to check
+	 * @param message the exception message to use if the assertion fails
+	 * @throws IllegalArgumentException if the collection is <code>null</code> or has no elements
+	 */
+	public static void notEmpty(Collection collection, String message) {
+		if (CollectionUtils.isEmpty(collection)) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	/**
+	 * Assert that a collection has elements; that is, it must not be
+	 * <code>null</code> and must have at least one element.
+	 * <pre class="code">Assert.notEmpty(collection, "Collection must have elements");</pre>
+	 * @param collection the collection to check
+	 * @throws IllegalArgumentException if the collection is <code>null</code> or has no elements
+	 */
+	public static void notEmpty(Collection collection) {
+		notEmpty(collection,
+				"[Assertion failed] - this collection must not be empty: it must contain at least 1 element");
+	}
+
+	public static void notEmpty(Collection collection, RuntimeException throwIfAssertFail) {
+		if (CollectionUtils.isEmpty(collection)) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that a Map has entries; that is, it must not be <code>null</code>
+	 * and must have at least one entry.
+	 * <pre class="code">Assert.notEmpty(map, "Map must have entries");</pre>
+	 * @param map the map to check
+	 * @param message the exception message to use if the assertion fails
+	 * @throws IllegalArgumentException if the map is <code>null</code> or has no entries
+	 */
+	public static void notEmpty(Map map, String message) {
+		if (CollectionUtils.isEmpty(map)) {
+			throw new IllegalArgumentException(message);
+		}
+	}
+
+	/**
+	 * Assert that a Map has entries; that is, it must not be <code>null</code>
+	 * and must have at least one entry.
+	 * <pre class="code">Assert.notEmpty(map);</pre>
+	 * @param map the map to check
+	 * @throws IllegalArgumentException if the map is <code>null</code> or has no entries
+	 */
+	public static void notEmpty(Map map) {
+		notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry");
+	}
+
+	public static void notEmpty(Map map, RuntimeException throwIfAssertFail) {
+		if (CollectionUtils.isEmpty(map)) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that the provided object is an instance of the provided class.
+	 * <pre class="code">Assert.instanceOf(Foo.class, foo);</pre>
+	 * @param type the type to check against
+	 * @param obj the object to check
+	 * @param message a message which will be prepended to the message produced by
+	 * the function itself, and which may be used to provide context. It should
+	 * normally end in a ": " or ". " so that the function generate message looks
+	 * ok when prepended to it.
+	 * @throws IllegalArgumentException if the object is not an instance of clazz
+	 * @see Class#isInstance
+	 */
+	public static void isInstanceOf(Class type, Object obj, String message) {
+		notNull(type, "Type to check against must not be null");
+		if (!type.isInstance(obj)) {
+			throw new IllegalArgumentException(message + "Object of class ["
+					+ (obj != null ? obj.getClass().getName() : "null") + "] must be an instance of " + type);
+		}
+	}
+
+	/**
+	 * Assert that the provided object is an instance of the provided class.
+	 * <pre class="code">Assert.instanceOf(Foo.class, foo);</pre>
+	 * @param clazz the required class
+	 * @param obj the object to check
+	 * @throws IllegalArgumentException if the object is not an instance of clazz
+	 * @see Class#isInstance
+	 */
+	public static void isInstanceOf(Class clazz, Object obj) {
+		isInstanceOf(clazz, obj, "");
+	}
+
+	public static void isInstanceOf(Class type, Object obj, RuntimeException throwIfAssertFail) {
+		notNull(type, "Type to check against must not be null");
+		if (!type.isInstance(obj)) {
+			throw throwIfAssertFail;
+		}
+	}
+
+	/**
+	 * Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>.
+	 * <pre class="code">Assert.isAssignable(Number.class, myClass);</pre>
+	 * @param superType the super type to check against
+	 * @param subType the sub type to check
+	 * @param message a message which will be prepended to the message produced by
+	 * the function itself, and which may be used to provide context. It should
+	 * normally end in a ": " or ". " so that the function generate message looks
+	 * ok when prepended to it.
+	 * @throws IllegalArgumentException if the classes are not assignable
+	 */
+	public static void isAssignable(Class superType, Class subType, String message) {
+		notNull(superType, "Type to check against must not be null");
+		if (subType == null || !superType.isAssignableFrom(subType)) {
+			throw new IllegalArgumentException(message + subType + " is not assignable to " + superType);
+		}
+	}
+
+	/**
+	 * Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>.
+	 * <pre class="code">Assert.isAssignable(Number.class, myClass);</pre>
+	 * @param superType the super type to check
+	 * @param subType the sub type to check
+	 * @throws IllegalArgumentException if the classes are not assignable
+	 */
+	public static void isAssignable(Class superType, Class subType) {
+		isAssignable(superType, subType, "");
+	}
+
+	/**
+	 * Assert a boolean expression, throwing <code>IllegalStateException</code>
+	 * if the test result is <code>false</code>. Call isTrue if you wish to
+	 * throw IllegalArgumentException on an assertion failure.
+	 * <pre class="code">Assert.state(id == null, "The id property must not already be initialized");</pre>
+	 * @param expression a boolean expression
+	 * @param message the exception message to use if the assertion fails
+	 * @throws IllegalStateException if expression is <code>false</code>
+	 */
+	public static void state(boolean expression, String message) {
+		if (!expression) {
+			throw new IllegalStateException(message);
+		}
+	}
+
+	/**
+	 * Assert a boolean expression, throwing {@link IllegalStateException}
+	 * if the test result is <code>false</code>.
+	 * <p>Call {@link #isTrue(boolean)} if you wish to
+	 * throw {@link IllegalArgumentException} on an assertion failure.
+	 * <pre class="code">Assert.state(id == null);</pre>
+	 * @param expression a boolean expression
+	 * @throws IllegalStateException if the supplied expression is <code>false</code>
+	 */
+	public static void state(boolean expression) {
+		state(expression, "[Assertion failed] - this state invariant must be true");
+	}
+}

+ 79 - 0
src/main/java/com/key/common/utils/CookieUtils.java

@@ -0,0 +1,79 @@
+package com.key.common.utils;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class CookieUtils {
+	/**
+	 * 添加cookie
+	 * 
+	 * @param response
+	 * @param name
+	 *            Cookie的名称,不能为null
+	 * @param value
+	 *            Cookie的值,默认值空字符串
+	 * @param maxAge
+	 * @param path
+	 *            默认值'/'
+	 */
+	public static void addCookie(HttpServletResponse response, String name,
+			String value, Integer maxAge, String path) {
+		if (value == null) {
+			value = "";
+		}
+		if (path == null) {
+			path = "/";
+		}
+
+		Cookie cookie = new Cookie(name, value);
+		cookie.setPath(path);
+		if (maxAge != null) {
+			cookie.setMaxAge(maxAge);
+		}
+
+		response.addCookie(cookie);
+	}
+	
+	/**
+	 * 设置cookie
+	 * 
+	 * @param response
+	 * @param name
+	 *            cookie名字
+	 * @param value
+	 *            cookie值
+	 * @param maxAge
+	 *            cookie生命周期 以秒为单位
+	 */
+	public static void addCookie(HttpServletResponse response, String name,
+			String value, int maxAge) {
+		Cookie cookie = new Cookie(name, value);
+		cookie.setPath("/");
+		if (maxAge > 0)
+			cookie.setMaxAge(maxAge);
+		response.addCookie(cookie);
+	}
+
+
+	/**
+	 * @param request
+	 * @param cookieName
+	 * @return 指定的cookie
+	 */
+	public static Cookie getCookie(HttpServletRequest request, String cookieName) {
+		Cookie[] cookies = request.getCookies();
+		if (cookies == null) {
+			return null;
+		}
+
+		for (Cookie c : cookies) {
+			if (c.getName().equals(cookieName)) {
+				return c;
+			}
+		}
+
+		return null;
+	}
+
+}

+ 71 - 0
src/main/java/com/key/common/utils/DiaowenProperty.java

@@ -0,0 +1,71 @@
+package com.key.common.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.struts2.ServletActionContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+
+import com.baidu.ueditor.ConfigManager;
+import com.sun.org.apache.xml.internal.security.Init;
+
+/**
+ * 
+ * @author keyuan
+ *
+ */
+public class DiaowenProperty extends
+		PropertyPlaceholderConfigurer {
+
+	public static String DWSTORAGETYPE = null;
+	public static String ACCESS_KEY_ID = null;
+	public static String SECRET_ACCESS_KEY = null;
+	public static String ENDPOINT = null;
+	public static String STORAGE_URL_PREFIX = null;
+
+	public static String WENJUANHTML_BACKET = null;
+	public static String UPLOADFILE_BACKET = null;
+	public static String UPLOADFILE_JM_BACKET = null;
+
+//	private static Map<String, String> ctxPropertiesMap;
+
+	@Override
+	protected void processProperties(
+			ConfigurableListableBeanFactory beanFactoryToProcess,
+			Properties props) throws BeansException {
+		super.processProperties(beanFactoryToProcess, props);
+		
+		DWSTORAGETYPE = props.getProperty("dw.storage.type");
+		ACCESS_KEY_ID = props.getProperty("dw.yunos.access_keyid");
+		SECRET_ACCESS_KEY = props.getProperty("dw.yunos.access_keysecret");
+		ENDPOINT = props.getProperty("dw.yunos.endpoint");
+//		FILE_BACKET_DOMAIN = props.getProperty("dw.yunos.file_backet_domain");
+		STORAGE_URL_PREFIX = props.getProperty("dw.storage.url_prefix");
+		
+		WENJUANHTML_BACKET = props.getProperty("dw.yunos.wenjuan_html_backet");
+		UPLOADFILE_BACKET = props.getProperty("dw.yunos.upload_file_backet");
+		UPLOADFILE_JM_BACKET = props.getProperty("dw.yunos.upload_file_jm_backet");
+		/*
+		ctxPropertiesMap = new HashMap<String, String>();
+		for (Object key : props.keySet()) {
+			String keyStr = key.toString();
+			String value = props.getProperty(keyStr);
+			ctxPropertiesMap.put(keyStr, value);
+		}
+		*/
+		
+	}
+/*
+	public static String getContextProperty(String name) {
+	    return ctxPropertiesMap.get(name);
+	}
+*/
+	public void diaowenInit(){
+		System.out.println("系统初始化方法。。。");
+		System.out.println(ServletActionContext.getContext());
+	}
+	
+}

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels