Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
171b5f426f | ||
|
|
e2664614da | ||
|
|
a64991f5e3 | ||
|
|
39ec6649d5 | ||
|
|
80a5f83791 | ||
|
|
5204015db5 | ||
|
|
80a35fec5d | ||
|
|
9d19595c9a | ||
|
|
2cffa9c396 | ||
|
|
fac969bd9c | ||
|
|
596f6eee4e | ||
|
|
7fc8394cbd | ||
|
|
c0ab584687 | ||
|
|
ff5c7ef05b | ||
|
|
b470509623 | ||
|
|
87c0a7116f | ||
|
|
4bc10be699 | ||
|
|
13af0ac9f9 | ||
|
|
c1684b51a2 | ||
|
|
a73ee3688d | ||
|
|
2d81b86b10 | ||
|
|
2fd28e18f9 | ||
|
|
d5d05050e3 | ||
|
|
ada63af9dc | ||
|
|
c9ecd3cfc8 | ||
|
|
fe030b75c6 | ||
|
|
8563888fd5 | ||
|
|
39a5f6164d | ||
|
|
8b3a20b68b | ||
|
|
f6f824054a | ||
|
|
9e163b1034 | ||
|
|
1f92830aec | ||
|
|
85c50bbd40 | ||
|
|
6c7decc4a3 | ||
|
|
bfabf1a85e | ||
|
|
5706c8bfc9 | ||
|
|
27434ee26e | ||
|
|
7bcf1095ff | ||
|
|
01abf24665 | ||
|
|
8f4724fab2 | ||
|
|
b908885634 | ||
|
|
91d0e233f9 | ||
|
|
cfdc99f190 | ||
|
|
c553d966d6 | ||
|
|
0267908ece | ||
|
|
7fdcecb912 | ||
|
|
e1b6cdc831 | ||
|
|
596b1245d9 | ||
|
|
145e0b6b07 | ||
|
|
437220e34a | ||
|
|
28e1cd6f1d | ||
|
|
09286c8287 | ||
|
|
b195480441 | ||
|
|
ec73aa0ab0 | ||
|
|
55bc4dd3ad | ||
|
|
7a82d8a31c | ||
|
|
3e6044d902 | ||
|
|
15dcb1b27d | ||
|
|
849b3a7ec0 | ||
|
|
225a6a94ad | ||
|
|
8c52dd5db1 | ||
|
|
300bbd5f8f | ||
|
|
099ce0758b | ||
|
|
f91bb55f38 | ||
|
|
0e67815b8d | ||
|
|
19ba6daea7 | ||
|
|
45a09933b0 | ||
|
|
fc88e47a4b | ||
|
|
dc088a4764 | ||
|
|
6895d57cfa | ||
|
|
1b09cf9969 | ||
|
|
086ca1d882 | ||
|
|
d336c0fcf7 | ||
|
|
9736100fdc | ||
|
|
38acf1ae16 | ||
|
|
7ffa86df6e | ||
|
|
2a8a7edb83 | ||
|
|
4cf49b7446 | ||
|
|
9db7917975 | ||
|
|
5dfa01c421 | ||
|
|
4f8e2ccb4e | ||
|
|
b643b97603 | ||
|
|
e651f23210 | ||
|
|
8ecd600155 | ||
|
|
45fabc8ca0 | ||
|
|
89fdfc2070 | ||
|
|
1880b0bc4c | ||
|
|
949e747435 | ||
|
|
f2fb1af04f | ||
|
|
ddcf75b856 | ||
|
|
638c57b9c0 | ||
|
|
7da392e574 | ||
|
|
c21bf3ebfd | ||
|
|
b1380add20 | ||
|
|
d001756f6e | ||
|
|
941be6a52e | ||
|
|
378bec08f2 | ||
|
|
47e2f219f5 | ||
|
|
81793205c1 | ||
|
|
e55fb4274d | ||
|
|
0af6fedef8 | ||
|
|
a8cc129464 | ||
|
|
26ee250d4a | ||
|
|
f44d13ddec | ||
|
|
606f773ebc | ||
|
|
300dfdcd78 | ||
|
|
5a9c225a41 | ||
|
|
a1577453c3 | ||
|
|
2288884964 | ||
|
|
686a138234 | ||
|
|
1058c49b7f | ||
|
|
e6f6a45d67 | ||
|
|
f067c9eabd | ||
|
|
f2c8f7eef9 | ||
|
|
33246189e4 | ||
|
|
3e97365364 | ||
|
|
0fa8578d7e | ||
|
|
8b07f0b136 | ||
|
|
94c38ee018 | ||
|
|
56941e07b5 | ||
|
|
1fdbfe99b6 | ||
|
|
0ddda6a824 | ||
|
|
489b85df81 | ||
|
|
226d20d759 | ||
|
|
98ab05793b | ||
|
|
d98a0dbe30 | ||
|
|
c17b24b556 | ||
|
|
6e45b2e0c2 | ||
|
|
2f4a4b18f8 | ||
|
|
e1608eda1f | ||
|
|
131e0332e0 | ||
|
|
4b76a942cd | ||
|
|
78e27724af | ||
|
|
d28151b6b2 | ||
|
|
1e19211f93 |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -2,18 +2,23 @@
|
||||
**/target
|
||||
**/webapp/userfiles
|
||||
**/WEB-INF/classes
|
||||
**/transaction-logs
|
||||
**/logs/*.log*
|
||||
*.epoch
|
||||
*.lic
|
||||
|
||||
.settings
|
||||
.apt_generated
|
||||
.factorypath
|
||||
.classpath
|
||||
.project
|
||||
.vscode
|
||||
|
||||
.idea
|
||||
*.ipr
|
||||
*.iml
|
||||
*.iws
|
||||
*.lic
|
||||
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
*.epoch
|
||||
rebel.xml
|
||||
@@ -1,2 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
||||
@@ -1,4 +0,0 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
3
LICENSE
3
LICENSE
@@ -877,4 +877,5 @@ For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
理解您的用意。
|
||||
5. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议、版权声明和其他
|
||||
原作者规定需要包含的说明(请尊重原作者的著作权,不要删除或修改文件中的`@author`信息)。
|
||||
6. 您可以应用于商业软件,但必须遵循以上条款原则(请协助改进本作品)。
|
||||
6. 您可以应用于商业软件,但必须遵循以上条款原则(请协助改进本作品 http://jeesite.com)。
|
||||
7. 您若套用本平台的一些代码或功能参考,需要在您的软件介绍明显位置说明出处。
|
||||
|
||||
118
README.md
118
README.md
@@ -1,106 +1,106 @@
|
||||
# 引言
|
||||
|
||||
JeeSite 是一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Spring MVC、Apache Shiro、MyBatis、Beetl、Bootstrap、AdminLTE),在线代码生成功能,包括核心模块如:组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、工作流等。采用松耦合设计;界面无刷新,一键换肤;众多账号安全设置,密码策略;在线定时任务配置;支持集群,支持SAAS;支持多数据源。
|
||||
## 交流方式
|
||||
|
||||
JeeSite 快速开发平台的主要目的是能够让初级的研发人员快速的开发出复杂的业务功能,让开发者注重专注业务,其余有平台来封装技术细节,降低技术难度,从而节省人力成本,缩短项目周期,提高软件安全质量。
|
||||
* 交流 QQ 群(千人大群):`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)`
|
||||
* 问题反馈:<https://gitee.com/thinkgem/jeesite4/issues> [【新手必读】](https://gitee.com/thinkgem/jeesite4/issues/I18ARR)
|
||||
* 码云Gitee:<https://gitee.com/thinkgem/jeesite4>
|
||||
* GitHub:<https://github.com/thinkgem/jeesite4>
|
||||
* 作者博客:<https://my.oschina.net/thinkgem>
|
||||
* **技术服务:**<http://s.jeesite.com>
|
||||
* 官方网站:<http://jeesite.com>
|
||||
* 官方论坛:<http://jeesite.net>
|
||||
* 关注微信公众号,了解最新动态:
|
||||
|
||||
JeeSite 自开源以来已被广大爱好者用到了企业、政府、医疗、金融、互联网等各个领域中,JeeSite 依架构简单精良、易于扩展、大众思维的设计模式,深入开发者的内心,并得到一致好评,于[2016](http://www.oschina.net/project/top_cn_2016?sort=1)和[2017](http://www.oschina.net/project/top_cn_2017?sort=1)连续两年获得开源中国《最受欢迎中国开源软件》奖杯,期间也帮助了不少刚毕业的大学生作为入门教材,快速的去实践。
|
||||

|
||||
|
||||
现在 JeeSite 4.0 来了,4.0的升级,作者结合了多年总结和经验,以及各方面的应用案例,对架构完成了一次全部重构,也纳入很多新的思想。不管是从开发者模式、底层架构、逻辑处理还是到用户界面,用户交互体验上都有很大的进步,在不忘学习成本、提高开发效率的情况下,安全方面也做和很多工作,包括:身份认证、密码策略、安全审计、日志收集。
|
||||
## 平台介绍
|
||||
|
||||
# 快速了解 JeeSite 4.0
|
||||
JeeSite 快速开发平台,不仅仅是一个后台开发框架,它是一个企业级快速开发解决方案,基于经典技术组合(Spring Boot、Spring MVC、Apache Shiro、MyBatis、Beetl、Bootstrap、AdminLTE)采用经典开发模式,让初学者能够更快的入门并投入到团队开发中去。在线代码生成功能,包括模块如:组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、工作流等。采用松耦合设计,模块增减便捷;界面无刷新,一键换肤;众多账号安全设置,密码策略;文件在线预览;消息推送;多元化第三方登录;在线定时任务配置;支持集群,支持SAAS;支持多数据源;支持读写分离、分库分表;支持微服务应用。
|
||||
|
||||
* **JeeSite 4.0 新特性、技术选型**
|
||||
JeeSite 快速开发平台的主要目的是能够让初级的研发人员快速的开发出复杂的业务功能(经典架构会的人多),让开发者注重专注业务,其余有平台来封装技术细节,降低技术难度,从而节省人力成本,缩短项目周期,提高软件安全质量。
|
||||
|
||||
<https://my.oschina.net/thinkgem/blog/913777>
|
||||
JeeSite 自 2013 年发布以来已被广大爱好者用到了企业、政府、医疗、金融、互联网等各个领域中,JeeSite 架构精良、易于扩展、大众思维的设计模式、工匠精神打磨每一个细节,深入开发者的内心,并荣获开源中国《最受欢迎中国开源软件》奖杯,期间也帮助了不少刚毕业的大学生,教师作为入门教材,快速的去实践。
|
||||
|
||||
* **JeeSite 4.0 简化MyBatis持久层开发**
|
||||
JeeSite4 的升级,作者结合了多年总结和经验,以及各方面的应用案例,对架构完成了一次全部重构,也纳入很多新的思想。不管是从开发者模式、底层架构、逻辑处理还是到用户界面,用户交互体验上都有很大的进步,在不忘学习成本、提高开发效率的情况下,安全方面也做和很多工作,包括:身份认证、密码策略、安全审计、日志收集。努力为大中小微企业打造全方位企业级快速开发解决方案。
|
||||
|
||||
<https://my.oschina.net/thinkgem/blog/1503611>
|
||||
学会使用 JeeSite 的知识点非常多,也非常少,因为她使用的都是一些通用的技术,通俗的设计风格,多数基础知识点大家都能掌握。 你只需要学会 JeeSite 的功能使用及组件应用就可以完成开发了。
|
||||
|
||||
* **JeeSite 4.0 简化业务逻辑层开发**
|
||||
### 4.x 的新特性及优势:<http://jeesite.com/docs/feature/>
|
||||
|
||||
<https://my.oschina.net/thinkgem/blog/1538766>
|
||||
## 技术选型
|
||||
|
||||
* **JeeSite 4.0 MVC层及前端组件介绍**
|
||||
* 主框架:Spring Boot 1.5、Spring Framework 4.3、Apache Shiro 1.6
|
||||
* 持久层:Apache MyBatis 3.4、Hibernate Validation 5.3、Alibaba Druid 1.1
|
||||
* 视图层:Spring MVC 4.3、Beetl 2.7 替换JSP、Bootstrap 3.3、AdminLTE 2.4
|
||||
* 前端组件:jQuery 1.12、jqGrid 4.7、layer 3.0、zTree 3.5、jquery-validation
|
||||
* 工具组件:Apache Commons、Logback 1.1、Jackson 2.8、POI 3.14、Quartz 2.2
|
||||
* 技术选型详情:<http://jeesite.com/docs/technology/>
|
||||
|
||||
<https://my.oschina.net/thinkgem/blog/1561129>
|
||||
## 内置功能
|
||||
|
||||
* **JeeSite 4.0 内置功能模块介绍**
|
||||
* <http://jeesite.com/docs/function/>
|
||||
|
||||
<https://my.oschina.net/thinkgem/blog/1609852>
|
||||
|
||||
<https://my.oschina.net/thinkgem/blog/1630671>
|
||||
## 生态系统
|
||||
|
||||
* **JeeSite 4.0 开发文档**
|
||||
|
||||
<http://jeesite4.mydoc.io>
|
||||
* 分布式微服务系统(Spring Cloud):<https://gitee.com/thinkgem/jeesite4-cloud>
|
||||
* JFlow工作流引擎:<https://gitee.com/thinkgem/jeesite4-jflow> :<http://ccflow.org>
|
||||
* Flowable业务流程模块(BPM):<http://jeesite.com/docs/bpm/>
|
||||
* 内容管理模块(CMS):<https://gitee.com/thinkgem/jeesite4-cms>
|
||||
|
||||
# 快速体验
|
||||
|
||||
### 在线演示
|
||||
|
||||
* 地址:<http://demo.jeesite.net/>
|
||||
* 账号:system
|
||||
* 密码:admin
|
||||
1. 地址:<http://demo.jeesite.com/>
|
||||
2. 账号:system
|
||||
3. 密码:admin
|
||||
|
||||
### 本地运行
|
||||
|
||||
1. 环境准备:`JDK 1.8`、`Maven 3.3`、`MySQL 5.7`
|
||||
2. 下载源码:<https://gitee.com/thinkgem/jeesite4/attach_files>
|
||||
3. 打开文件 /web`/src/main/resources/config/jeesite.yml` 配置JDBC连接
|
||||
4. 执行脚本 /web`/bin/init-data.bat` 初始化数据库
|
||||
5. 执行脚本 /web`/bin/run-tomcat.bat` 启动服务即可
|
||||
6. 浏览器访问 <http://127.0.0.1:8980/js/> 账号 system 密码 admin
|
||||
2. 执行命令:`git clone https://gitee.com/thinkgem/jeesite4.git` 下载源码
|
||||
3. 打开文件:`/web/src/main/resources/config/jeesite.yml` 配置JDBC连接
|
||||
4. 执行脚本:`/web/bin/init-data.bat` 初始化数据库
|
||||
5. 执行脚本:`/web/bin/run-tomcat.bat` 启动服务即可
|
||||
6. 浏览器访问:<http://127.0.0.1:8980/js/> 账号 system 密码 admin
|
||||
7. 部署常见问题:<http://jeesite.com/docs/faq/>
|
||||
|
||||
### 开发环境
|
||||
|
||||
* **开发环境部署运行调试**
|
||||
1. 部署运行文档:<http://jeesite.com/docs/install-deploy/>
|
||||
2. 部署常见问题:<http://jeesite.com/docs/faq/>
|
||||
|
||||
<http://jeesite4.mydoc.io/?t=267354>
|
||||
## 在线文档
|
||||
|
||||
* **常见问题汇总**
|
||||
* 在线文档学习地址:<http://docs.jeesite.com>
|
||||
|
||||
<http://jeesite4.mydoc.io/?t=284210>
|
||||
## 技术服务与支持
|
||||
|
||||
# 今后如何升级?
|
||||
* 没有资金的支撑就很难得到发展,特别是一个好的产品,如果 JeeSite 帮助了您,请为我们点赞。支持我们,您可以得到一些回报,有了这些我们会把公益事业做的更好,回报社区和社会,请给我们一些动力吧,在此非常感谢已支持我们的朋友!
|
||||
* **联系方式(官方商务)QQ:[1766571055](http://wpa.qq.com/msgrd?v=3&uin=1766571055&site=qq&menu=yes)**
|
||||
* 技术服务支持网页:<http://s.jeesite.com>
|
||||
|
||||
尽量不修改web项目以外的源码项目,如 jeesite-common、jeesite-modele-core,如果修改了,请 Pull Requests 上来,否则代码编码将与官方不同步,将对你的日后升级带来困难。
|
||||
|
||||
JeeSite的小版本(4.0.x)升级是非常便捷的,你只需要将 pom.xml 文件中的 parent.version 版本修改到最新版本即可,同版本下你可进行Maven快照强制更新,即可将最新版的依赖jar更新到本地,下面介绍一下在Eclipse里如何操作:
|
||||
|
||||
在web项目上右键,选择菜单 -> Maven -> Update Project...(或按Alt+F5) -> 点击 Select All 按钮 -> 选择 Force Update of Snapshots/Releases 复选框 -> 点击OK按钮即可。
|
||||
|
||||
如果进行相对大的版本(4.x.x)升级这里我们会附加一个声明,帮助你进行迁移操作。
|
||||
|
||||
# 授权协议声明
|
||||
## 授权协议声明
|
||||
|
||||
1. 已开源的代码,授权协议采用 AGPL v3 + Apache Licence v2 进行发行。
|
||||
2. 您可以免费使用、修改和衍生代码,但不允许修改后和衍生的代码做为闭源软件发布。
|
||||
3. 修改后和衍生的代码必须也按照AGPL协议进行流通,对修改后和衍生的代码必须向社会公开。
|
||||
4. 如果您修改了代码,需要在被修改的文件中进行说明,并遵守代码格式规范,帮助他人更好的理解您的用意。
|
||||
5. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议、版权声明和其他原作者规定需要包含的说明(请尊重原作者的著作权,不要删除或修改文件中的`@author`信息)。
|
||||
5. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议、版权声明和其他原作者规定
|
||||
需要包含的说明(请尊重原作者的著作权,不要删除或修改文件中的`@author`信息)。
|
||||
6. 您可以应用于商业软件,但必须遵循以上条款原则(请协助改进本作品)。
|
||||
7. 关系平台的发展战略考虑,底层部分代码暂未开源,但这不影响您的二次开发。
|
||||
8. 请知悉社区版,用户数不可超过100个,最大允许10个用户同时在线(不含匿名)。
|
||||
7. 您若套用本平台的一些代码或功能参考,需要在您的软件介绍明显位置说明出处。
|
||||
8. **当前 v4.0.8 版本,没有系统用户数量限制,没有最大在线人数限制。**
|
||||
|
||||
### 付费服务:<http://jeesite4.mydoc.io/?t=267685>
|
||||
## 今后如何升级?
|
||||
|
||||
* 本服务的推出,是我们对您服务的一个保障,也是我们的唯一经济来源,有了这些我们会把开源事业做的更好,让JeeSite能够快速的成长起来,请给我们一些动力吧,谢谢您的支持!
|
||||
尽量不修改 web 项目以外的源码项目,如 jeesite-common、jeesite-modele-core,如果修改了,请 Pull Requests 上来,否则代码与官方不同步,会将对你的日后升级增加难度。
|
||||
|
||||
# 技术交流方式
|
||||
如果您修改了依赖模块代码,也没关系,这时你需要利用 Git 版本控制工具,与官方仓库代码进行同步,合并代码即可。
|
||||
|
||||
* QQ 群号: `127515876(已满)` `209330483(已满)` `223507718(已满)` `709534275` `730390092`
|
||||
* 入群须知:目前为付费群,刚入群会有5分钟禁言,腾讯预设置的,无法解除,稍等片刻即可正常发言;由于群容量有限,为了维持运营千人QQ群的所需支付的QQ年费会员费用,故开启付费入群模式,申请者只需支付少量金额即可加入,这样也可以保证只有真实交流需求的人进入,避免闲杂做广告人员的乱入;新手提问前,请先阅读此[【文章】](http://www.dianbo.org/9238/stone/tiwendezhihui.htm)。
|
||||
* Gitee:<https://gitee.com/thinkgem/jeesite4>
|
||||
* GitHub:<https://github.com/thinkgem/jeesite4>
|
||||
* 问题反馈:<https://gitee.com/thinkgem/jeesite4/issues>
|
||||
* 作者博客:<https://my.oschina.net/thinkgem/blog>
|
||||
* 官方网站:<http://jeesite.com>
|
||||
* 微信公众号:
|
||||
|
||||

|
||||
每个版本升级,我们都会附带详细更新日志:<http://jeesite.com/docs/upgrade/>。
|
||||
|
||||
在这里,你可以看到 JeeSite 新增哪些新功能和改进,在每个版本下都有对应升级方法。
|
||||
|
||||
# Git 全局设置技巧
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/main/resources=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
encoding/<project>=UTF-8
|
||||
@@ -1,8 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
@@ -1,4 +0,0 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="jeesite-common">
|
||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faceted-project>
|
||||
<installed facet="jst.utility" version="1.0"/>
|
||||
<installed facet="java" version="1.7"/>
|
||||
</faceted-project>
|
||||
@@ -1,2 +0,0 @@
|
||||
disabled=06target
|
||||
eclipse.preferences.version=1
|
||||
@@ -12,6 +12,6 @@ echo.
|
||||
cd %~dp0
|
||||
|
||||
cd ..
|
||||
call mvn clean javadoc:jar
|
||||
call mvn clean package -Pjavadoc
|
||||
|
||||
pause
|
||||
@@ -4,11 +4,11 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.jeesite</groupId>
|
||||
<artifactId>jeesite-parent</artifactId>
|
||||
<version>4.0.3-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>com.jeesite</groupId>
|
||||
<artifactId>jeesite-parent</artifactId>
|
||||
<version>4.0.8-SNAPSHOT</version>
|
||||
<relativePath>../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>jeesite-common</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -161,8 +161,8 @@
|
||||
|
||||
<!-- Apache HTTP -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Jsoup HTTP -->
|
||||
|
||||
@@ -8,6 +8,8 @@ package com.jeesite.common.codec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
@@ -17,6 +19,7 @@ import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
|
||||
@@ -167,7 +170,9 @@ public class EncodeUtils {
|
||||
* URL 解码, Encode默认为UTF-8.
|
||||
*/
|
||||
public static String decodeUrl(String part, String encoding) {
|
||||
|
||||
if (part == null){
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return URLDecoder.decode(part, encoding);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
@@ -181,30 +186,29 @@ public class EncodeUtils {
|
||||
public static String decodeUrl2(String part) {
|
||||
return decodeUrl(decodeUrl(part));
|
||||
}
|
||||
|
||||
|
||||
// 预编译XSS过滤正则表达式
|
||||
private static Pattern p1 = Pattern.compile("<\\s*(script|link|style|iframe)\\s([\\s\\S]+?)<\\/\\s*\\1\\s*>", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern p2 = Pattern.compile("\\s*on[a-z]+\\s*=\\s*(\"[^\"]+\"|'[^']+'|[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern p3 = Pattern.compile("\\s*(href|src)\\s*=\\s*(\"\\s*(javascript|vbscript):[^\"]+\"|'\\s*(javascript|vbscript):[^']+'|(javascript|vbscript):[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern p4 = Pattern.compile("epression\\((.|\\n)*\\);?", Pattern.CASE_INSENSITIVE);
|
||||
private static List<Pattern> xssPatterns = ListUtils.newArrayList(
|
||||
Pattern.compile("(<\\s*(script|link|style|iframe)([\\s\\S]*?)(>|<\\/\\s*\\1\\s*>))|(</\\s*(script|link|style|iframe)\\s*>)", Pattern.CASE_INSENSITIVE),
|
||||
Pattern.compile("\\s*(href|src)\\s*=\\s*(\"\\s*(javascript|vbscript):[^\"]+\"|'\\s*(javascript|vbscript):[^']+'|(javascript|vbscript):[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE),
|
||||
Pattern.compile("\\s*on[a-z]+\\s*=\\s*(\"[^\"]+\"|'[^']+'|[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE),
|
||||
Pattern.compile("(eval\\((.|\\n)*\\)|xpression\\((.|\\n)*\\))", Pattern.CASE_INSENSITIVE)
|
||||
);
|
||||
|
||||
/**
|
||||
* XSS 非法字符过滤
|
||||
* 内容以<!--HTML-->开头的用以下规则(保留标签,去掉js脚本):
|
||||
* 1、<\s*(script|link|style|iframe)\s([\s\S]+?)<\/\s*\1\s*>
|
||||
* 2、\s*on[a-z]+\s*=\s*("[^"]+"|'[^']+'|[^\s]+)\s*(?=>)
|
||||
* 3、\s*(href|src)\s*=\s*("\s*(javascript|vbscript):[^"]+"|'\s*(javascript|vbscript):[^']+'|(javascript|vbscript):[^\s]+)\s*(?=>)
|
||||
* 4、epression\((.|\n)*\);?
|
||||
* 其它情况下:进行HTML4编码
|
||||
* XSS 非法字符过滤,内容以<!--HTML-->开头的用以下规则(保留标签)
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static String xssFilter(String text) {
|
||||
String oriValue = StringUtils.trim(text);
|
||||
if (text != null){
|
||||
String oriValue = StringUtils.trim(text), value = oriValue;
|
||||
value = p1.matcher(value).replaceAll("");
|
||||
value = p2.matcher(value).replaceAll("");
|
||||
value = p3.matcher(value).replaceAll("");
|
||||
value = p4.matcher(value).replaceAll("");
|
||||
String value = oriValue;
|
||||
for (Pattern pattern : xssPatterns) {
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
if (matcher.find()) {
|
||||
value = matcher.replaceAll(StringUtils.EMPTY);
|
||||
}
|
||||
}
|
||||
// 如果开始不是HTML,XML,JOSN格式,则再进行HTML的 "、<、> 转码。
|
||||
if (!StringUtils.startsWithIgnoreCase(value, "<!--HTML-->") // HTML
|
||||
&& !StringUtils.startsWithIgnoreCase(value, "<?xml ") // XML
|
||||
@@ -215,7 +219,7 @@ public class EncodeUtils {
|
||||
value = value.replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">");
|
||||
}
|
||||
if (logger.isInfoEnabled() && !value.equals(oriValue)){
|
||||
logger.info("xssFilter: {} to {}", text, value);
|
||||
logger.info("xssFilter: {} <=<=<= {}", value, text);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -223,7 +227,7 @@ public class EncodeUtils {
|
||||
}
|
||||
|
||||
// 预编译SQL过滤正则表达式
|
||||
private static Pattern p5 = Pattern.compile("(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern sqlPattern = Pattern.compile("(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* SQL过滤,防止注入,传入参数输入有select相关代码,替换空。
|
||||
@@ -231,13 +235,48 @@ public class EncodeUtils {
|
||||
*/
|
||||
public static String sqlFilter(String text){
|
||||
if (text != null){
|
||||
String value = p5.matcher(text).replaceAll("");
|
||||
String value = text;
|
||||
Matcher matcher = sqlPattern.matcher(text);
|
||||
if (matcher.find()) {
|
||||
value = matcher.replaceAll(StringUtils.EMPTY);
|
||||
}
|
||||
if (logger.isWarnEnabled() && !value.equals(text)){
|
||||
logger.warn("sqlFilter: {} to {}", text, value);
|
||||
logger.info("sqlFilter: {} <=<=<= {}", value, text);
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// xssFilter("你好,<script>alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("你好,<strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,\"><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<iframe src=\"abcdef\"></iframe><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<iframe src=\"abcdef\"/><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<iframe src=\"abcdef\"><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script type=\"text/javascript\">alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script\n type=\"text/javascript\">\nalert(document.cookie)\n</script>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script src='' onerror='alert(document.cookie)'></script>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script type=text/javascript>alert()我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script>alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script>window.location='url'我还在。");
|
||||
// xssFilter("<!--HTML-->你好,</script></iframe>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,eval(abc)我还在。");
|
||||
// xssFilter("<!--HTML-->你好,xpression(abc)我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<img src='abc.jpg' onerror='location='';alert(document.cookie);'></img>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<img src='abc.jpg' onerror='alert(document.cookie);'/>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<img src='abc.jpg' onerror='alert(document.cookie);'>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a onload='alert(\"abc\")'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a href=\"/abc\">hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a href='/abc'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a href='vbscript:alert(\"abc\");'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a href='javascript:alert(\"abc\");'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,?abc=def&hello=123&world={\"a\":1}我还在。");
|
||||
// sqlFilter("你好,select * from xxx where abc=def and 1=1我还在。");
|
||||
// sqlFilter("你好,insert into xxx values(1,2,3,4,5)我还在。");
|
||||
// sqlFilter("你好,delete from xxx我还在。");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -3,12 +3,16 @@
|
||||
*/
|
||||
package com.jeesite.common.codec;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.jeesite.common.io.IOUtils;
|
||||
|
||||
/**
|
||||
* MD5不可逆加密工具类
|
||||
* @author ThinkGem
|
||||
@@ -17,7 +21,6 @@ public class Md5Utils {
|
||||
|
||||
private static final String MD5 = "MD5";
|
||||
private static final String DEFAULT_ENCODING = "UTF-8";
|
||||
|
||||
|
||||
/**
|
||||
* 对输入字符串进行md5散列.
|
||||
@@ -63,5 +66,36 @@ public class Md5Utils {
|
||||
public static byte[] md5(InputStream input) throws IOException {
|
||||
return DigestUtils.digest(input, MD5);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的MD5值
|
||||
*/
|
||||
public static String md5File(File file) {
|
||||
return md5File(file, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的MD5值,支持获取文件部分的MD5值
|
||||
*/
|
||||
public static String md5File(File file, int size) {
|
||||
if (file != null && file.exists()){
|
||||
InputStream in = null;
|
||||
try {
|
||||
byte[] bytes = null;
|
||||
in = FileUtils.openInputStream(file);
|
||||
if (size != -1 && file.length() >= size){
|
||||
bytes = IOUtils.toByteArray(in, size);
|
||||
}else{
|
||||
bytes = IOUtils.toByteArray(in);
|
||||
}
|
||||
return EncodeUtils.encodeHex(md5(bytes));
|
||||
} catch (IOException e) {
|
||||
return StringUtils.EMPTY;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -383,7 +383,8 @@ public class ListUtils extends org.apache.commons.collections.ListUtils {
|
||||
public static <T> List<T> listOrderBy(List<T> list, String orderBy){
|
||||
if (list != null && StringUtils.isNotBlank(orderBy)){
|
||||
final String[] ss = orderBy.trim().split(" ");
|
||||
if (ss != null && ss.length == 2){
|
||||
if (ss != null){
|
||||
final String t = ss.length==2 ? ss[1] : "asc";
|
||||
Collections.sort(list, new Comparator<T>() {
|
||||
@Override
|
||||
public int compare(T o1, T o2) {
|
||||
@@ -395,12 +396,13 @@ public class ListUtils extends org.apache.commons.collections.ListUtils {
|
||||
s1 = ObjectUtils.toString(ReflectUtils.invokeGetter(o1, ss[0]));
|
||||
s2 = ObjectUtils.toString(ReflectUtils.invokeGetter(o2, ss[0]));
|
||||
}
|
||||
if ("asc".equals(ss[1])){
|
||||
if ("asc".equalsIgnoreCase(t)){
|
||||
return s1.compareTo(s2);
|
||||
}else{
|
||||
return s2.compareTo(s1);
|
||||
}
|
||||
}});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
||||
@@ -814,14 +814,14 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
// logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (raf != null) {
|
||||
try {
|
||||
raf.close();
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
// logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -948,6 +948,10 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 取不到,取当前工作路径
|
||||
if (StringUtils.isBlank(projectPath)){
|
||||
projectPath = System.getProperty("user.dir");
|
||||
}
|
||||
return projectPath;
|
||||
}
|
||||
|
||||
@@ -982,6 +986,10 @@ public class FileUtils extends org.apache.commons.io.FileUtils {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 取不到,取当前工作路径
|
||||
if (StringUtils.isBlank(webappPath)){
|
||||
webappPath = System.getProperty("user.dir");
|
||||
}
|
||||
return webappPath;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.core.io.Resource;
|
||||
|
||||
import com.jeesite.common.collect.SetUtils;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* Properties工具类, 可载入多个properties、yml文件,
|
||||
@@ -33,9 +34,7 @@ public class PropertiesUtils {
|
||||
|
||||
// 默认加载的文件,可通过继承覆盖(若有相同Key,优先加载后面的)
|
||||
public static final String[] DEFAULT_CONFIG_FILE = new String[]{
|
||||
"classpath:config/jeesite.yml",
|
||||
"classpath:config/application.yml",
|
||||
"classpath:application.yml"};
|
||||
"classpath:config/application.yml", "classpath:application.yml"};
|
||||
|
||||
private static Logger logger = PropertiesUtils.initLogger();
|
||||
|
||||
@@ -50,16 +49,53 @@ public class PropertiesUtils {
|
||||
releadInstance();
|
||||
}
|
||||
public static void releadInstance(){
|
||||
Set<String> configFiles = SetUtils.newLinkedHashSet();
|
||||
// 获取平台及模块相关的配置文件
|
||||
Set<String> configSet = SetUtils.newLinkedHashSet();
|
||||
Resource[] resources = ResourceUtils.getResources("classpath*:/config/jeesite-*.*");
|
||||
for(Resource resource : resources){
|
||||
configFiles.add("classpath:/config/"+resource.getFilename());
|
||||
configSet.add("classpath:config/"+resource.getFilename());
|
||||
}
|
||||
configSet.add("classpath:config/jeesite.yml");
|
||||
// 获取全局设置默认的配置文件(以下是支持环境配置的属性文件)
|
||||
Set<String> set = SetUtils.newLinkedHashSet();
|
||||
for (String configFile : DEFAULT_CONFIG_FILE){
|
||||
configFiles.add(configFile);
|
||||
set.add(configFile);
|
||||
}
|
||||
logger.debug("Loading jeesite config: {}", configFiles);
|
||||
INSTANCE = new PropertiesUtils(configFiles.toArray(new String[configFiles.size()]));
|
||||
// 获取 spring.config.location 外部自定义的配置文件
|
||||
String customConfigs = System.getProperty("spring.config.location");
|
||||
if (StringUtils.isNotBlank(customConfigs)){
|
||||
for (String customConfig : StringUtils.split(customConfigs, ",")){
|
||||
if (!customConfig.contains("$")){
|
||||
customConfig = org.springframework.util.StringUtils.cleanPath(customConfig);
|
||||
if (!ResourceUtils.isUrl(customConfig)){
|
||||
customConfig = ResourceUtils.FILE_URL_PREFIX + customConfig;
|
||||
}
|
||||
}
|
||||
set.add(customConfig);
|
||||
}
|
||||
}
|
||||
// 获取 spring.profiles.active 活动环境名称的配置文件
|
||||
String[] configFiles = set.toArray(new String[set.size()]);
|
||||
String profiles = System.getProperty("spring.profiles.active");
|
||||
if (StringUtils.isBlank(profiles)){
|
||||
PropertiesUtils propsTemp = new PropertiesUtils(configFiles);
|
||||
profiles = propsTemp.getProperty("spring.profiles.active");
|
||||
}
|
||||
for (String location : configFiles){
|
||||
configSet.add(location);
|
||||
if (StringUtils.isNotBlank(profiles) && !StringUtils.equals(profiles, "default")){
|
||||
if (location.endsWith(".properties")){
|
||||
configSet.add(StringUtils.substringBeforeLast(location, ".properties")
|
||||
+ "-" + profiles + ".properties");
|
||||
}else if (location.endsWith(".yml")){
|
||||
configSet.add(StringUtils.substringBeforeLast(location, ".yml")
|
||||
+ "-" + profiles + ".yml");
|
||||
}
|
||||
}
|
||||
}
|
||||
configFiles = configSet.toArray(new String[configSet.size()]);
|
||||
logger.debug("Loading jeesite config: {}", (Object)configFiles);
|
||||
INSTANCE = new PropertiesUtils(configFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +107,7 @@ public class PropertiesUtils {
|
||||
try {
|
||||
Resource resource = ResourceUtils.getResource(location);
|
||||
if (resource.exists()){
|
||||
String ext = FileUtils.getFileExtension(location);
|
||||
if ("properties".equals(ext)){
|
||||
if (location.endsWith(".properties")){
|
||||
InputStreamReader is = null;
|
||||
try {
|
||||
is = new InputStreamReader(resource.getInputStream(), "UTF-8");
|
||||
@@ -83,7 +118,7 @@ public class PropertiesUtils {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
else if ("yml".equals(ext)){
|
||||
else if (location.endsWith(".yml")){
|
||||
YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean();
|
||||
bean.setResources(resource);
|
||||
for (Map.Entry<Object,Object> entry : bean.getObject().entrySet()){
|
||||
@@ -95,6 +130,8 @@ public class PropertiesUtils {
|
||||
} catch (Exception e) {
|
||||
logger.error("Load " + location + " failure. ", e);
|
||||
}
|
||||
// 存储当前加载的配置文件路径和名称
|
||||
properties.setProperty("configFiles", StringUtils.join(configFiles, ","));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +170,7 @@ public class PropertiesUtils {
|
||||
while(m.find()) {
|
||||
String g = m.group();
|
||||
String keyChild = g.replaceAll("\\$\\{", "").replaceAll("\\}", "");
|
||||
value = value.replace(g, getProperty(keyChild));
|
||||
value = StringUtils.replace(value, g, getProperty(keyChild));
|
||||
}
|
||||
return value;
|
||||
}else{
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
|
||||
@@ -20,7 +21,12 @@ import com.jeesite.common.lang.ExceptionUtils;
|
||||
*/
|
||||
public class ResourceUtils extends org.springframework.util.ResourceUtils {
|
||||
|
||||
private static ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
private static ResourceLoader resourceLoader;
|
||||
private static ResourcePatternResolver resourceResolver;
|
||||
static{
|
||||
resourceLoader = new DefaultResourceLoader();
|
||||
resourceResolver = new PathMatchingResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源加载器(可读取jar内的文件)
|
||||
@@ -79,11 +85,7 @@ public class ResourceUtils extends org.springframework.util.ResourceUtils {
|
||||
*/
|
||||
public static Resource[] getResources(String locationPattern){
|
||||
try {
|
||||
Resource[] resources = new PathMatchingResourcePatternResolver()
|
||||
.getResources(locationPattern);
|
||||
// System.out.println("===========\n===========");
|
||||
// System.out.println(locationPattern + " : " + resources.length);
|
||||
// System.out.println("===========\n===========");
|
||||
Resource[] resources = resourceResolver.getResources(locationPattern);
|
||||
return resources;
|
||||
} catch (IOException e) {
|
||||
throw ExceptionUtils.unchecked(e);
|
||||
|
||||
@@ -17,6 +17,10 @@ public class ByteUtils {
|
||||
* @return
|
||||
*/
|
||||
public static String formatByteSize(long byteSize) {
|
||||
|
||||
if (byteSize <= -1){
|
||||
return String.valueOf(byteSize);
|
||||
}
|
||||
|
||||
double size = 1.0 * byteSize;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package com.jeesite.common.lang;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
* BigDecimal工具类
|
||||
@@ -92,4 +93,19 @@ public class NumberUtils extends org.apache.commons.lang3.math.NumberUtils {
|
||||
return bg.setScale(0, BigDecimal.ROUND_HALF_UP).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数值类型
|
||||
* @param data
|
||||
* @param pattern
|
||||
*/
|
||||
public static String formatNumber(Object data, String pattern) {
|
||||
DecimalFormat df = null;
|
||||
if (pattern == null) {
|
||||
df = new DecimalFormat();
|
||||
} else {
|
||||
df = new DecimalFormat(pattern);
|
||||
}
|
||||
return df.format(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,13 +14,14 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.nustaq.serialization.FSTConfiguration;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
import com.jeesite.common.io.IOUtils;
|
||||
|
||||
/**
|
||||
* 对象操作工具类, 继承org.apache.commons.lang3.ObjectUtils类
|
||||
* @author ThinkGem
|
||||
* @version 2014-6-29
|
||||
* @version 2018-08-11
|
||||
*/
|
||||
public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
|
||||
@@ -212,73 +213,14 @@ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
// // Kryo不是线程安全的,所以要建立一个线程变量,每一个线程实例化一次
|
||||
// public static final ThreadLocal<Kryo> kryos = new ThreadLocal<Kryo>() {
|
||||
// @Override
|
||||
// protected Kryo initialValue() {
|
||||
// Kryo kryo = new Kryo();
|
||||
// // 设置false关闭注册行为, Kryo支持对注册行为,如kryo.register(SomeClazz.class);
|
||||
// // 这会赋予该Class一个从0开始的编号,但Kryo使用注册行为最大的问题在于,
|
||||
// // 其不保证同一个Class每一次注册的号码想用,这与注册的顺序有关,也就意味着在不同的机器、
|
||||
// // 同一个机器重启前后都有可能拥有不同的编号,这会导致序列化产生问题,所以在分布式项目中,一般关闭注册行为。
|
||||
// kryo.setRegistrationRequired(false);
|
||||
// // 支持循环引用
|
||||
// kryo.setReferences(true);
|
||||
// return kryo;
|
||||
// };
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * Kryo序列化对象
|
||||
// * @param object
|
||||
// * @return
|
||||
// */
|
||||
// public static byte[] serializeKryo(Object object) {
|
||||
// byte[] bytes = null;
|
||||
// Output output = null;
|
||||
// try {
|
||||
// if (object != null) {
|
||||
// output = new Output(1024, -1);
|
||||
// kryos.get().writeClassAndObject(output, object);
|
||||
// bytes = output.toBytes();
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// } finally {
|
||||
// if (output != null) {
|
||||
// output.close();
|
||||
// }
|
||||
// }
|
||||
// return bytes;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Kryo反序列化对象
|
||||
// * @param bytes
|
||||
// * @return
|
||||
// */
|
||||
// public static Object unserializeKryo(byte[] bytes) {
|
||||
// Object object = null;
|
||||
// Input input = null;
|
||||
// try {
|
||||
// if (bytes != null && bytes.length > 0) {
|
||||
// input = new Input(bytes, 0, bytes.length);
|
||||
// object = kryos.get().readClassAndObject(input);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// } finally {
|
||||
// if (input != null) {
|
||||
// input.close();
|
||||
// }
|
||||
// }
|
||||
// return object;
|
||||
// }
|
||||
|
||||
// FST序列化配置对象
|
||||
private static FSTConfiguration fst = FSTConfiguration.createDefaultConfiguration();
|
||||
|
||||
private static ThreadLocal<FSTConfiguration> fst = new NamedThreadLocal<FSTConfiguration>("FSTConfiguration") {
|
||||
public FSTConfiguration initialValue() {
|
||||
return FSTConfiguration.createDefaultConfiguration();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* FST 序列化对象
|
||||
* @param object
|
||||
@@ -289,7 +231,7 @@ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
return null;
|
||||
}
|
||||
long beginTime = System.currentTimeMillis();
|
||||
byte[] bytes = fst.asByteArray(object);
|
||||
byte[] bytes = fst.get().asByteArray(object);
|
||||
long totalTime = System.currentTimeMillis() - beginTime;
|
||||
if (totalTime > 3000){
|
||||
System.out.println("Fst serialize time: " + TimeUtils.formatDateAgo(totalTime));
|
||||
@@ -307,7 +249,7 @@ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils {
|
||||
return null;
|
||||
}
|
||||
long beginTime = System.currentTimeMillis();
|
||||
Object object = fst.asObject(bytes);
|
||||
Object object = fst.get().asObject(bytes);
|
||||
long totalTime = System.currentTimeMillis() - beginTime;
|
||||
if (totalTime > 3000){
|
||||
System.out.println("Fst unserialize time: " + TimeUtils.formatDateAgo(totalTime));
|
||||
|
||||
@@ -250,16 +250,14 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
s = s.toLowerCase();
|
||||
|
||||
StringBuilder sb = new StringBuilder(s.length());
|
||||
boolean upperCase = false;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == SEPARATOR) {
|
||||
upperCase = true;
|
||||
upperCase = i != 1; // 不允许第二个字符是大写
|
||||
} else if (upperCase) {
|
||||
sb.append(Character.toUpperCase(c));
|
||||
upperCase = false;
|
||||
@@ -267,7 +265,6 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -297,18 +294,14 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean upperCase = false;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
boolean nextUpperCase = true;
|
||||
|
||||
if (i < (s.length() - 1)) {
|
||||
nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
|
||||
}
|
||||
|
||||
if ((i > 0) && Character.isUpperCase(c)) {
|
||||
if (!upperCase || !nextUpperCase) {
|
||||
sb.append(SEPARATOR);
|
||||
@@ -317,10 +310,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
} else {
|
||||
upperCase = false;
|
||||
}
|
||||
|
||||
sb.append(Character.toLowerCase(c));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,10 @@
|
||||
*/
|
||||
package com.jeesite.common.mail;
|
||||
|
||||
import org.apache.commons.mail.HtmlEmail;
|
||||
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
|
||||
/**
|
||||
* 发送电子邮件
|
||||
*/
|
||||
@Deprecated
|
||||
public class EmailUtils {
|
||||
|
||||
/**
|
||||
@@ -19,14 +16,9 @@ public class EmailUtils {
|
||||
* @param content 内容
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean sendEmail(String toAddress, String subject, String content) {
|
||||
PropertiesUtils loader = PropertiesUtils.getInstance();
|
||||
String fromAddress = loader.getProperty("msg.email.fromAddress");
|
||||
String fromPassword = loader.getProperty("msg.email.fromPassword");
|
||||
String fromHostName = loader.getProperty("msg.email.fromHostName");
|
||||
String sslOnConnect = loader.getProperty("msg.email.sslOnConnect", "false");
|
||||
String sslSmtpPort = loader.getProperty("msg.email.sslSmtpPort");
|
||||
return sendEmail(fromAddress, fromPassword, fromHostName, sslOnConnect, sslSmtpPort, toAddress, subject, content);
|
||||
return com.jeesite.common.msg.EmailUtils.send(toAddress, subject, content);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,296 +28,10 @@ public class EmailUtils {
|
||||
* @param content 内容
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean sendEmail(String fromAddress, String fromPassword, String fromHostName,
|
||||
String sslOnConnect, String sslSmtpPort, String toAddress, String subject, String content) {
|
||||
try {
|
||||
HtmlEmail htmlEmail = new HtmlEmail();
|
||||
// 发送地址
|
||||
htmlEmail.setFrom(fromAddress);
|
||||
// 密码校验
|
||||
htmlEmail.setAuthentication(fromAddress, fromPassword);
|
||||
// 发送服务器协议
|
||||
htmlEmail.setHostName(fromHostName);
|
||||
|
||||
// SSL
|
||||
if ("true".equals(sslOnConnect)) {
|
||||
htmlEmail.setSSLOnConnect(true);
|
||||
htmlEmail.setSslSmtpPort(sslSmtpPort);
|
||||
}
|
||||
|
||||
// 接收地址
|
||||
htmlEmail.addTo(toAddress);
|
||||
|
||||
// 标题
|
||||
htmlEmail.setSubject(subject);
|
||||
// 内容
|
||||
htmlEmail.setMsg(content);
|
||||
|
||||
// 其他信息
|
||||
htmlEmail.setCharset("utf-8");
|
||||
|
||||
// 发送
|
||||
htmlEmail.send();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
|
||||
return com.jeesite.common.msg.EmailUtils.send(fromAddress, fromPassword, fromHostName, sslOnConnect, sslSmtpPort, toAddress, subject, content);
|
||||
}
|
||||
|
||||
// // private static final String smtphost = "192.168.1.70";
|
||||
// private static final String from = "thinkgem@163.com";
|
||||
// private static final String fromName = "测试公司";
|
||||
// private static final String charSet = "utf-8";
|
||||
// private static final String username = "thinkgem@163.com";
|
||||
// private static final String password = "123456";
|
||||
//
|
||||
// private static Map<String, String> hostMap = new HashMap<String, String>();
|
||||
// static {
|
||||
// // 126
|
||||
// hostMap.put("smtp.126", "smtp.126.com");
|
||||
// // qq
|
||||
// hostMap.put("smtp.qq", "smtp.qq.com");
|
||||
//
|
||||
// // 163
|
||||
// hostMap.put("smtp.163", "smtp.163.com");
|
||||
//
|
||||
// // sina
|
||||
// hostMap.put("smtp.sina", "smtp.sina.com.cn");
|
||||
//
|
||||
// // tom
|
||||
// hostMap.put("smtp.tom", "smtp.tom.com");
|
||||
//
|
||||
// // 263
|
||||
// hostMap.put("smtp.263", "smtp.263.net");
|
||||
//
|
||||
// // yahoo
|
||||
// hostMap.put("smtp.yahoo", "smtp.mail.yahoo.com");
|
||||
//
|
||||
// // hotmail
|
||||
// hostMap.put("smtp.hotmail", "smtp.live.com");
|
||||
//
|
||||
// // gmail
|
||||
// hostMap.put("smtp.gmail", "smtp.gmail.com");
|
||||
// hostMap.put("smtp.port.gmail", "465");
|
||||
// }
|
||||
//
|
||||
// public static String getHost(String email) throws Exception {
|
||||
// Pattern pattern = Pattern.compile("\\w+@(\\w+)(\\.\\w+){1,2}");
|
||||
// Matcher matcher = pattern.matcher(email);
|
||||
// String key = "unSupportEmail";
|
||||
// if (matcher.find()) {
|
||||
// key = "smtp." + matcher.group(1);
|
||||
// }
|
||||
// if (hostMap.containsKey(key)) {
|
||||
// return hostMap.get(key);
|
||||
// } else {
|
||||
// throw new Exception("unSupportEmail");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static int getSmtpPort(String email) throws Exception {
|
||||
// Pattern pattern = Pattern.compile("\\w+@(\\w+)(\\.\\w+){1,2}");
|
||||
// Matcher matcher = pattern.matcher(email);
|
||||
// String key = "unSupportEmail";
|
||||
// if (matcher.find()) {
|
||||
// key = "smtp.port." + matcher.group(1);
|
||||
// }
|
||||
// if (hostMap.containsKey(key)) {
|
||||
// return Integer.parseInt(hostMap.get(key));
|
||||
// } else {
|
||||
// return 25;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 发送模板邮件
|
||||
// *
|
||||
// * @param toMailAddr 收信人地址
|
||||
// * @param subject email主题
|
||||
// * @param templatePath 模板地址
|
||||
// * @param map 模板map
|
||||
// */
|
||||
// public static void sendFtlMail(String toMailAddr, String subject, String templatePath, Map<String, Object> map) {
|
||||
// Template template = null;
|
||||
// Configuration freeMarkerConfig = null;
|
||||
// HtmlEmail hemail = new HtmlEmail();
|
||||
// try {
|
||||
// hemail.setHostName(getHost(from));
|
||||
// hemail.setSmtpPort(getSmtpPort(from));
|
||||
// hemail.setCharset(charSet);
|
||||
// hemail.addTo(toMailAddr);
|
||||
// hemail.setFrom(from, fromName);
|
||||
// hemail.setAuthentication(username, password);
|
||||
// hemail.setSubject(subject);
|
||||
// freeMarkerConfig = new Configuration();
|
||||
// freeMarkerConfig.setDirectoryForTemplateLoading(new File(getFilePath()));
|
||||
// // 获取模板
|
||||
// template = freeMarkerConfig.getTemplate(getFileName(templatePath), new Locale("Zh_cn"), "UTF-8");
|
||||
// // 模板内容转换为string
|
||||
// String htmlText = FreeMarkers.renderTemplate(template, map);
|
||||
// System.out.println(htmlText);
|
||||
// hemail.setMsg(htmlText);
|
||||
// hemail.send();
|
||||
// System.out.println("email send true!");
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// System.out.println("email send error!");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 发送普通邮件
|
||||
// *
|
||||
// * @param toMailAddr 收信人地址
|
||||
// * @param subject email主题
|
||||
// * @param message 发送email信息
|
||||
// */
|
||||
// public static void sendCommonMail(String toMailAddr, String subject, String message) {
|
||||
// HtmlEmail hemail = new HtmlEmail();
|
||||
// try {
|
||||
// hemail.setHostName(getHost(from));
|
||||
// hemail.setSmtpPort(getSmtpPort(from));
|
||||
// hemail.setCharset(charSet);
|
||||
// hemail.addTo(toMailAddr);
|
||||
// hemail.setFrom(from, fromName);
|
||||
// hemail.setAuthentication(username, password);
|
||||
// hemail.setSubject(subject);
|
||||
// hemail.setMsg(message);
|
||||
// hemail.send();
|
||||
// System.out.println("email send true!");
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// System.out.println("email send error!");
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public static String getHtmlText(String templatePath, Map<String, Object> map) {
|
||||
// Template template = null;
|
||||
// String htmlText = "";
|
||||
// try {
|
||||
// Configuration freeMarkerConfig = null;
|
||||
// freeMarkerConfig = new Configuration();
|
||||
// freeMarkerConfig.setDirectoryForTemplateLoading(new File(getFilePath()));
|
||||
// // 获取模板
|
||||
// template = freeMarkerConfig.getTemplate(getFileName(templatePath), new Locale("Zh_cn"), "UTF-8");
|
||||
// // 模板内容转换为string
|
||||
// htmlText = FreeMarkers.renderTemplate(template, map);
|
||||
// System.out.println(htmlText);
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// return htmlText;
|
||||
// }
|
||||
//
|
||||
// private static String getFilePath() {
|
||||
// String path = getAppPath(SendMailUtil.class);
|
||||
// path = path + File.separator + "mailtemplate" + File.separator;
|
||||
// path = path.replace("\\", "/");
|
||||
// System.out.println(path);
|
||||
// return path;
|
||||
// }
|
||||
//
|
||||
// private static String getFileName(String path) {
|
||||
// path = path.replace("\\", "/");
|
||||
// System.out.println(path);
|
||||
// return path.substring(path.lastIndexOf("/") + 1);
|
||||
// }
|
||||
//
|
||||
// // @SuppressWarnings("unchecked")
|
||||
// public static String getAppPath(Class<?> cls) {
|
||||
// // 检查用户传入的参数是否为空
|
||||
// if (cls == null)
|
||||
// throw new java.lang.IllegalArgumentException("参数不能为空!");
|
||||
// ClassLoader loader = cls.getClassLoader();
|
||||
// // 获得类的全名,包括包名
|
||||
// String clsName = cls.getName() + ".class";
|
||||
// // 获得传入参数所在的包
|
||||
// Package pack = cls.getPackage();
|
||||
// String path = "";
|
||||
// // 如果不是匿名包,将包名转化为路径
|
||||
// if (pack != null) {
|
||||
// String packName = pack.getName();
|
||||
// // 此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库
|
||||
// if (packName.startsWith("java.") || packName.startsWith("javax."))
|
||||
// throw new java.lang.IllegalArgumentException("不要传送系统类!");
|
||||
// // 在类的名称中,去掉包名的部分,获得类的文件名
|
||||
// clsName = clsName.substring(packName.length() + 1);
|
||||
// // 判定包名是否是简单包名,如果是,则直接将包名转换为路径,
|
||||
// if (packName.indexOf(".") < 0)
|
||||
// path = packName + "/";
|
||||
// else {// 否则按照包名的组成部分,将包名转换为路径
|
||||
// int start = 0, end = 0;
|
||||
// end = packName.indexOf(".");
|
||||
// while (end != -1) {
|
||||
// path = path + packName.substring(start, end) + "/";
|
||||
// start = end + 1;
|
||||
// end = packName.indexOf(".", start);
|
||||
// }
|
||||
// path = path + packName.substring(start) + "/";
|
||||
// }
|
||||
// }
|
||||
// // 调用ClassLoader的getResource方法,传入包含路径信息的类文件名
|
||||
// java.net.URL url = loader.getResource(path + clsName);
|
||||
// // 从URL对象中获取路径信息
|
||||
// String realPath = url.getPath();
|
||||
// // 去掉路径信息中的协议名"file:"
|
||||
// int pos = realPath.indexOf("file:");
|
||||
// if (pos > -1)
|
||||
// realPath = realPath.substring(pos + 5);
|
||||
// // 去掉路径信息最后包含类文件信息的部分,得到类所在的路径
|
||||
// pos = realPath.indexOf(path + clsName);
|
||||
// realPath = realPath.substring(0, pos - 1);
|
||||
// // 如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名
|
||||
// if (realPath.endsWith("!"))
|
||||
// realPath = realPath.substring(0, realPath.lastIndexOf("/"));
|
||||
// /*------------------------------------------------------------
|
||||
// ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径
|
||||
// 中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要
|
||||
// 的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的
|
||||
// 中文及空格路径
|
||||
// -------------------------------------------------------------*/
|
||||
// try {
|
||||
// realPath = java.net.URLDecoder.decode(realPath, "utf-8");
|
||||
// } catch (Exception e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// System.out.println("realPath----->" + realPath);
|
||||
// return realPath;
|
||||
// }
|
||||
//
|
||||
// // private static File getFile(String path){
|
||||
// // File file =
|
||||
// // SendMail.class.getClassLoader().getResource("mailtemplate/test.ftl").getFile();
|
||||
// // return file;
|
||||
// // }
|
||||
// //
|
||||
//
|
||||
// public static void main(String[] args) {
|
||||
// // HtmlEmail hemail = new HtmlEmail();
|
||||
// // try {
|
||||
// // hemail.setHostName("smtp.exmail.qq.com");
|
||||
// // hemail.setCharset("utf-8");
|
||||
// // hemail.addTo("test@qq.com");
|
||||
// // hemail.setFrom("test@qq.com", "test");
|
||||
// // hemail.setAuthentication("test@test.com", "test@aa");
|
||||
// // hemail.setSubject("sendemail test!");
|
||||
// // hemail.setMsg("<a href=\"http://www.google.cn\">谷歌</a><br/>");
|
||||
// // hemail.send();
|
||||
// // System.out.println("email send true!");
|
||||
// // } catch (Exception e) {
|
||||
// // e.printStackTrace();
|
||||
// // System.out.println("email send error!");
|
||||
// // }
|
||||
// Map<String, Object> map = new HashMap<String, Object>();
|
||||
// map.put("subject", "测试标题");
|
||||
// map.put("content", "测试 内容");
|
||||
// String templatePath = "mailtemplate/test.ftl";
|
||||
// sendFtlMail("test@163.com", "sendemail test!", templatePath, map);
|
||||
//
|
||||
// // System.out.println(getFileName("mailtemplate/test.ftl"));
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import java.util.TimeZone;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
@@ -46,6 +47,8 @@ public class JsonMapper extends ObjectMapper {
|
||||
}
|
||||
|
||||
public JsonMapper() {
|
||||
// Spring ObjectMapper 初始化配置,支持 @JsonView
|
||||
new Jackson2ObjectMapperBuilder().configure(this);
|
||||
// 为Null时不序列化
|
||||
this.setSerializationInclusion(Include.NON_NULL);
|
||||
// 允许单引号
|
||||
@@ -61,7 +64,7 @@ public class JsonMapper extends ObjectMapper {
|
||||
@Override
|
||||
public void serialize(Object value, JsonGenerator jgen,
|
||||
SerializerProvider provider) throws IOException, JsonProcessingException {
|
||||
jgen.writeString("");
|
||||
jgen.writeString(StringUtils.EMPTY);
|
||||
}
|
||||
});
|
||||
// // 统一默认Date类型转换格式。如果设置,Bean中的@JsonFormat将失效
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.dom4j.Element;
|
||||
import org.dom4j.Namespace;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
|
||||
@@ -46,6 +47,8 @@ public class XmlMapper extends com.fasterxml.jackson.dataformat.xml.XmlMapper{
|
||||
* 构造方法
|
||||
*/
|
||||
public XmlMapper() {
|
||||
// Spring ObjectMapper 初始化配置,支持 @JsonView
|
||||
new Jackson2ObjectMapperBuilder().configure(this);
|
||||
// 设置时区
|
||||
this.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
|
||||
}
|
||||
|
||||
80
common/src/main/java/com/jeesite/common/msg/EmailUtils.java
Normal file
80
common/src/main/java/com/jeesite/common/msg/EmailUtils.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.common.msg;
|
||||
|
||||
import org.apache.commons.mail.HtmlEmail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
|
||||
/**
|
||||
* 发送电子邮件
|
||||
*/
|
||||
public class EmailUtils {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(EmailUtils.class);
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
* @param toAddress 接收地址
|
||||
* @param subject 标题
|
||||
* @param content 内容
|
||||
* @return
|
||||
*/
|
||||
public static boolean send(String toAddress, String subject, String content) {
|
||||
PropertiesUtils props = PropertiesUtils.getInstance();
|
||||
String fromAddress = props.getProperty("msg.email.fromAddress");
|
||||
String fromPassword = props.getProperty("msg.email.fromPassword");
|
||||
String fromHostName = props.getProperty("msg.email.fromHostName");
|
||||
String sslOnConnect = props.getProperty("msg.email.sslOnConnect", "false");
|
||||
String sslSmtpPort = props.getProperty("msg.email.sslSmtpPort");
|
||||
return send(fromAddress, fromPassword, fromHostName, sslOnConnect, sslSmtpPort, toAddress, subject, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
* @param toAddress 接收地址
|
||||
* @param subject 标题
|
||||
* @param content 内容
|
||||
* @return
|
||||
*/
|
||||
public static boolean send(String fromAddress, String fromPassword, String fromHostName,
|
||||
String sslOnConnect, String sslSmtpPort, String toAddress, String subject, String content) {
|
||||
try {
|
||||
HtmlEmail htmlEmail = new HtmlEmail();
|
||||
// 发送地址
|
||||
htmlEmail.setFrom(fromAddress);
|
||||
// 密码校验
|
||||
htmlEmail.setAuthentication(fromAddress, fromPassword);
|
||||
// 发送服务器协议
|
||||
htmlEmail.setHostName(fromHostName);
|
||||
|
||||
// SSL
|
||||
if ("true".equals(sslOnConnect)) {
|
||||
htmlEmail.setSSLOnConnect(true);
|
||||
htmlEmail.setSslSmtpPort(sslSmtpPort);
|
||||
}
|
||||
|
||||
// 接收地址
|
||||
htmlEmail.addTo(toAddress);
|
||||
|
||||
// 标题
|
||||
htmlEmail.setSubject(subject);
|
||||
// 内容
|
||||
htmlEmail.setMsg(content);
|
||||
|
||||
// 其他信息
|
||||
htmlEmail.setCharset("utf-8");
|
||||
|
||||
// 发送
|
||||
htmlEmail.send();
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
logger.error(ex.getMessage(), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
43
common/src/main/java/com/jeesite/common/msg/SmsUtils.java
Normal file
43
common/src/main/java/com/jeesite/common/msg/SmsUtils.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.jeesite.common.msg;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 发送短信(请实现send方法)
|
||||
*/
|
||||
public class SmsUtils {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(SmsUtils.class);
|
||||
|
||||
/**
|
||||
* 模拟发送短信
|
||||
* @param content 短信内容
|
||||
* @param mobile 接受手机号码
|
||||
*/
|
||||
public static String send(String content, String mobile) {
|
||||
// PropertiesUtils props = PropertiesUtils.getInstance();
|
||||
// String url = props.getProperty("msg.sms.url");
|
||||
// String data = props.getProperty("msg.sms.data");
|
||||
// String prefix = props.getProperty("msg.sms.prefix", "");
|
||||
// String suffix = props.getProperty("msg.sms.suffix", "");
|
||||
// Connection conn = Jsoup.connect(url);
|
||||
// conn.postDataCharset("UTF-8");
|
||||
// conn.method(Method.POST);
|
||||
// for (String param : StringUtils.split(data, "&")){
|
||||
// String[] ss = StringUtils.split(param, "=");
|
||||
// if (ss.length == 1){
|
||||
// conn.data(ss[0], "");
|
||||
// }else if (ss.length == 2){
|
||||
// conn.data(ss[0], ss[1]);
|
||||
// }
|
||||
// }
|
||||
// // 手机号码
|
||||
// conn.data("mobile", mobile);
|
||||
// // 短信内容
|
||||
// conn.data("content", prefix + content + suffix);
|
||||
logger.warn("模拟发送短信成功!请实现 "+SmsUtils.class+" 的 send 方法。");
|
||||
return "{result:0,message:\"模拟发送短信成功!\"}";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,8 @@ package com.jeesite.common.network;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
|
||||
public class IpUtils {
|
||||
@@ -16,20 +17,23 @@ public class IpUtils {
|
||||
if (request == null) {
|
||||
return "unknown";
|
||||
}
|
||||
String ip = request.getHeader("X-Forwarded-For");
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
String ip = null;
|
||||
String xffName = PropertiesUtils.getInstance()
|
||||
.getProperty("shiro.remoteAddrHeaderName");
|
||||
if (StringUtils.isNotBlank(xffName)){
|
||||
ip = request.getHeader(xffName);
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("X-Real-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
return StringUtils.split(ObjectUtils.toString(ip), ",")[0];
|
||||
if (StringUtils.isNotBlank(ip)){
|
||||
ip = EncodeUtils.xssFilter(ip);
|
||||
ip = StringUtils.split(ip, ",")[0];
|
||||
}
|
||||
if (StringUtils.isBlank(ip)){
|
||||
ip = "unknown";
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -69,14 +69,16 @@ public class ReflectUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
|
||||
*/
|
||||
public static Object getFieldValue(final Object obj, final String fieldName) {
|
||||
Field field = getAccessibleField(obj, fieldName);
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
//throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
logger.warn("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
return null;
|
||||
}
|
||||
Object result = null;
|
||||
try {
|
||||
@@ -93,7 +95,9 @@ public class ReflectUtils {
|
||||
public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
|
||||
Field field = getAccessibleField(obj, fieldName);
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
//throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
logger.warn("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
field.set(obj, value);
|
||||
@@ -114,7 +118,9 @@ public class ReflectUtils {
|
||||
}
|
||||
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
|
||||
if (method == null) {
|
||||
throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
|
||||
//throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
|
||||
logger.warn("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return method.invoke(obj, args);
|
||||
@@ -132,7 +138,10 @@ public class ReflectUtils {
|
||||
public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
|
||||
Method method = getAccessibleMethodByName(obj, methodName, args.length);
|
||||
if (method == null) {
|
||||
throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
|
||||
// 如果为空不报错,直接返回空。
|
||||
// throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
|
||||
logger.warn("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// 类型转换(将参数数据类型转换为目标方法参数类型)
|
||||
@@ -141,6 +150,9 @@ public class ReflectUtils {
|
||||
if (args[i] != null && !args[i].getClass().equals(cs[i])){
|
||||
if (cs[i] == String.class){
|
||||
args[i] = ObjectUtils.toString(args[i]);
|
||||
if(StringUtils.endsWith((String)args[i], ".0")){
|
||||
args[i] = StringUtils.substringBefore((String)args[i], ".0");
|
||||
}
|
||||
}else if (cs[i] == Integer.class){
|
||||
args[i] = ObjectUtils.toInteger(args[i]);
|
||||
}else if (cs[i] == Long.class){
|
||||
@@ -171,7 +183,11 @@ public class ReflectUtils {
|
||||
* 如向上转型到Object仍无法找到, 返回null.
|
||||
*/
|
||||
public static Field getAccessibleField(final Object obj, final String fieldName) {
|
||||
Validate.notNull(obj, "object can't be null");
|
||||
// 为空不报错。直接返回 null
|
||||
// Validate.notNull(obj, "object can't be null");
|
||||
if (obj == null){
|
||||
return null;
|
||||
}
|
||||
Validate.notBlank(fieldName, "fieldName can't be blank");
|
||||
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
|
||||
try {
|
||||
@@ -194,7 +210,11 @@ public class ReflectUtils {
|
||||
*/
|
||||
public static Method getAccessibleMethod(final Object obj, final String methodName,
|
||||
final Class<?>... parameterTypes) {
|
||||
Validate.notNull(obj, "object can't be null");
|
||||
// 为空不报错。直接返回 null
|
||||
// Validate.notNull(obj, "object can't be null");
|
||||
if (obj == null){
|
||||
return null;
|
||||
}
|
||||
Validate.notBlank(methodName, "methodName can't be blank");
|
||||
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
|
||||
try {
|
||||
@@ -216,7 +236,11 @@ public class ReflectUtils {
|
||||
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
|
||||
*/
|
||||
public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) {
|
||||
Validate.notNull(obj, "object can't be null");
|
||||
// 为空不报错。直接返回 null
|
||||
// Validate.notNull(obj, "object can't be null");
|
||||
if (obj == null){
|
||||
return null;
|
||||
}
|
||||
Validate.notBlank(methodName, "methodName can't be blank");
|
||||
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
|
||||
Method[] methods = searchType.getDeclaredMethods();
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.jeesite.common.text;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.pinyin4j.PinyinHelper;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
|
||||
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
|
||||
|
||||
/**
|
||||
@@ -12,34 +15,16 @@ import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombi
|
||||
*/
|
||||
public class PinyinUtils {
|
||||
|
||||
// /**
|
||||
// * 将字符串中的中文转化为拼音,其他字符不变
|
||||
// * @param inputString
|
||||
// * @return
|
||||
// */
|
||||
// public static String getPinyin(String inputString) {
|
||||
// HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
|
||||
// format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
|
||||
// format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
// format.setVCharType(HanyuPinyinVCharType.WITH_V);
|
||||
//
|
||||
// char[] input = inputString.trim().toCharArray();
|
||||
// String output = "";
|
||||
//
|
||||
// try {
|
||||
// for (int i = 0; i < input.length; i++) {
|
||||
// if (java.lang.Character.toString(input[i]).matches("[\\u4E00-\\u9FA5]+")) {
|
||||
// String[] temp = PinyinHelper.toHanyuPinyinStringArray(input[i], format);
|
||||
// output += temp[0];
|
||||
// } else {
|
||||
// output += java.lang.Character.toString(input[i]);
|
||||
// }
|
||||
// }
|
||||
// } catch (BadHanyuPinyinOutputFormatCombination e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// return output;
|
||||
// }
|
||||
private static class Static{
|
||||
private static Pattern idPatt = Pattern.compile("\\W");
|
||||
private static HanyuPinyinOutputFormat defaultFormat;
|
||||
static{
|
||||
defaultFormat = new HanyuPinyinOutputFormat();
|
||||
defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
|
||||
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
defaultFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取汉字串拼音首字母,替换调非法标示符字符,英文字符不变,去除空格
|
||||
@@ -47,17 +32,30 @@ public class PinyinUtils {
|
||||
* @return 汉语拼音首字母
|
||||
*/
|
||||
public static String getFirstSpell(String chinese) {
|
||||
return getFirstSpell(chinese, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取汉字串拼音首字母,替换调非法标示符字符,英文字符不变,去除空格
|
||||
* @param chinese 汉字串
|
||||
* @param isId 是否标示符(true:将去掉特殊字符)
|
||||
* @return 汉语拼音首字母
|
||||
*/
|
||||
public static String getFirstSpell(String chinese, boolean isId) {
|
||||
chinese = getDbc(chinese);
|
||||
if (chinese == null){
|
||||
return null;
|
||||
}
|
||||
StringBuffer pybf = new StringBuffer();
|
||||
char[] arr = chinese.toCharArray();
|
||||
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
|
||||
defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
|
||||
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
if (arr[i] > 128) {
|
||||
try {
|
||||
String[] temp = PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat);
|
||||
String[] temp = PinyinHelper.toHanyuPinyinStringArray(arr[i], Static.defaultFormat);
|
||||
if (temp != null) {
|
||||
pybf.append(temp[0].charAt(0));
|
||||
}else{
|
||||
pybf.append(String.valueOf(arr[i]));
|
||||
}
|
||||
} catch (BadHanyuPinyinOutputFormatCombination e) {
|
||||
e.printStackTrace();
|
||||
@@ -66,7 +64,10 @@ public class PinyinUtils {
|
||||
pybf.append(arr[i]);
|
||||
}
|
||||
}
|
||||
return pybf.toString().replaceAll("\\W", "").trim();
|
||||
if (isId){
|
||||
return Static.idPatt.matcher(pybf.toString()).replaceAll("").trim();
|
||||
}
|
||||
return pybf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,17 +76,30 @@ public class PinyinUtils {
|
||||
* @return 汉语拼音
|
||||
*/
|
||||
public static String getFullSpell(String chinese) {
|
||||
return getFullSpell(chinese, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取汉字串全拼,英文字符不变
|
||||
* @param chinese 汉字串
|
||||
* @param isId 是否标示符(true:将去掉特殊字符)
|
||||
* @return 汉语拼音
|
||||
*/
|
||||
public static String getFullSpell(String chinese, boolean isId) {
|
||||
chinese = getDbc(chinese);
|
||||
if (chinese == null){
|
||||
return null;
|
||||
}
|
||||
StringBuffer pybf = new StringBuffer();
|
||||
char[] arr = chinese.toCharArray();
|
||||
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
|
||||
defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
|
||||
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
if (arr[i] > 128) {
|
||||
try {
|
||||
String[] ss = PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat);
|
||||
String[] ss = PinyinHelper.toHanyuPinyinStringArray(arr[i], Static.defaultFormat);
|
||||
if (ss != null && ss.length > 0){
|
||||
pybf.append(ss[0]);
|
||||
}else{
|
||||
pybf.append(String.valueOf(arr[i]));
|
||||
}
|
||||
} catch (BadHanyuPinyinOutputFormatCombination e) {
|
||||
e.printStackTrace();
|
||||
@@ -94,13 +108,57 @@ public class PinyinUtils {
|
||||
pybf.append(arr[i]);
|
||||
}
|
||||
}
|
||||
if (isId){
|
||||
return Static.idPatt.matcher(pybf.toString()).replaceAll("").trim();
|
||||
}
|
||||
return pybf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 半角转全角
|
||||
* @param input String.
|
||||
* @return 全角字符串.
|
||||
*/
|
||||
public static String getSbc(String input) {
|
||||
if (input == null){
|
||||
return null;
|
||||
}
|
||||
char c[] = input.toCharArray();
|
||||
for (int i = 0; i < c.length; i++) {
|
||||
if (c[i] == ' ') {
|
||||
c[i] = '\u3000';
|
||||
} else if (c[i] < '\177') {
|
||||
c[i] = (char) (c[i] + 65248);
|
||||
}
|
||||
}
|
||||
return new String(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全角转半角
|
||||
* @param input String.
|
||||
* @return 半角字符串
|
||||
*/
|
||||
public static String getDbc(String input) {
|
||||
if (input == null){
|
||||
return null;
|
||||
}
|
||||
char c[] = input.toCharArray();
|
||||
for (int i = 0; i < c.length; i++) {
|
||||
if (c[i] == '\u3000') {
|
||||
c[i] = ' ';
|
||||
} else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
|
||||
c[i] = (char) (c[i] - 65248);
|
||||
}
|
||||
}
|
||||
return new String(c);
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// String str = "你好,123,世界abc,~!#$_Sdf";
|
||||
//// System.out.println(getPinyin(str));
|
||||
// String str = "你好,123,世界abc,~!#$_Sdf,女;hello!-";
|
||||
// System.out.println(getFirstSpell(str));
|
||||
// System.out.println(getFirstSpell(str, false));
|
||||
// System.out.println(getFullSpell(str));
|
||||
// System.out.println(getFullSpell(str, false));
|
||||
// }
|
||||
}
|
||||
|
||||
24
common/src/main/java/com/jeesite/common/ueditor/Encoder.java
Normal file
24
common/src/main/java/com/jeesite/common/ueditor/Encoder.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.jeesite.common.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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
170
common/src/main/java/com/jeesite/common/ueditor/PathFormat.java
Normal file
170
common/src/main/java/com/jeesite/common/ueditor/PathFormat.java
Normal file
@@ -0,0 +1,170 @@
|
||||
package com.jeesite.common.ueditor;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
|
||||
public class PathFormat {
|
||||
|
||||
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"; // ThinkGem 添加自定义变量,获取当前用户ID
|
||||
|
||||
private static Date currentDate = null;
|
||||
|
||||
private static Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE );
|
||||
|
||||
public static String parse ( String input ) {
|
||||
|
||||
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 ) {
|
||||
|
||||
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( pattern );
|
||||
}
|
||||
|
||||
return pattern;
|
||||
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
}
|
||||
|
||||
private static String getUserid(String pattern) {
|
||||
String userId = null;
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
if (request != null){
|
||||
userId = (String)request.getSession().getAttribute("userCode");
|
||||
}
|
||||
return StringUtils.isNotBlank(userId) ? userId : "0";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.jeesite.common.ueditor.define;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 定义请求action类型
|
||||
* @author hancong03@baidu.com
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public final class ActionMap {
|
||||
|
||||
// 获取配置请求
|
||||
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;
|
||||
|
||||
public static final Map<String, Integer> mapping;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.jeesite.common.ueditor.define;
|
||||
|
||||
public enum ActionState {
|
||||
UNKNOW_ERROR
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.jeesite.common.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;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.jeesite.common.ueditor.define;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jeesite.common.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 );
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
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+"");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.jeesite.common.ueditor.define;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FileType {
|
||||
|
||||
public static final String JPG = "JPG";
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.jeesite.common.ueditor.define;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MIMEType {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.jeesite.common.ueditor.define;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jeesite.common.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 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.jeesite.common.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 ();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.jeesite.common.ueditor.hunter;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import com.jeesite.common.ueditor.PathFormat;
|
||||
import com.jeesite.common.ueditor.define.AppInfo;
|
||||
import com.jeesite.common.ueditor.define.BaseState;
|
||||
import com.jeesite.common.ueditor.define.MultiState;
|
||||
import com.jeesite.common.ueditor.define.State;
|
||||
|
||||
public class FileManager {
|
||||
|
||||
public static final String USERFILES_BASE_URL = "/userfiles/";
|
||||
|
||||
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.allowFiles = this.getAllowFiles( conf.get("allowFiles") );
|
||||
this.count = (Integer)conf.get( "count" );
|
||||
|
||||
}
|
||||
|
||||
public State listFile (HttpServletRequest request, int index ) {
|
||||
|
||||
// File dir = new File( this.dir );
|
||||
File dir = new File( PathFormat.parse(this.dir) ); // ThinkGem 路径中有变量时变量不转化问题
|
||||
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(request, fileList );
|
||||
}
|
||||
|
||||
state.putInfo( "start", index );
|
||||
state.putInfo( "total", list.size() );
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
private State getState (HttpServletRequest request, 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 ) ) );
|
||||
// ThinkGem 将绝对路径转换为虚拟路径
|
||||
String url = PathFormat.format( this.getPath( file ) );
|
||||
int index = url.indexOf(USERFILES_BASE_URL);
|
||||
if(index > 0) {
|
||||
url = url.substring(index + USERFILES_BASE_URL.length());
|
||||
}
|
||||
fileState.putInfo( "url", request.getContextPath() + USERFILES_BASE_URL + url );
|
||||
state.addState( fileState );
|
||||
}
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
private String getPath ( File file ) {
|
||||
|
||||
String path = 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.jeesite.common.ueditor.hunter;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.jeesite.common.ueditor.PathFormat;
|
||||
import com.jeesite.common.ueditor.define.AppInfo;
|
||||
import com.jeesite.common.ueditor.define.BaseState;
|
||||
import com.jeesite.common.ueditor.define.MIMEType;
|
||||
import com.jeesite.common.ueditor.define.MultiState;
|
||||
import com.jeesite.common.ueditor.define.State;
|
||||
import com.jeesite.common.ueditor.upload.StorageManager;
|
||||
|
||||
/**
|
||||
* 图片抓取器
|
||||
* @author hancong03@baidu.com
|
||||
*/
|
||||
public class ImageHunter {
|
||||
|
||||
private HttpServletRequest request = null;
|
||||
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 (HttpServletRequest request, Map<String, Object> conf ) {
|
||||
|
||||
this.request = request;
|
||||
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 );
|
||||
|
||||
if ( state.isSuccess() ) {
|
||||
state.putInfo( "url", request.getContextPath() + 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 ) {
|
||||
try {
|
||||
InetAddress ip = InetAddress.getByName(hostname);
|
||||
if (ip.isSiteLocalAddress()) {
|
||||
return false;
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.jeesite.common.ueditor.upload;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import com.jeesite.common.ueditor.PathFormat;
|
||||
import com.jeesite.common.ueditor.define.AppInfo;
|
||||
import com.jeesite.common.ueditor.define.BaseState;
|
||||
import com.jeesite.common.ueditor.define.FileType;
|
||||
import com.jeesite.common.ueditor.define.State;
|
||||
|
||||
public final class Base64Uploader {
|
||||
|
||||
public static State save(HttpServletRequest request, 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()) {
|
||||
String ctx = request.getContextPath(); // ThinkGem 修正上传图片后返回无contextpath问题
|
||||
storageState.putInfo("url", ctx + 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.jeesite.common.ueditor.upload;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
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;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import com.jeesite.common.io.FileUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.media.VideoUtils;
|
||||
import com.jeesite.common.ueditor.PathFormat;
|
||||
import com.jeesite.common.ueditor.define.ActionMap;
|
||||
import com.jeesite.common.ueditor.define.AppInfo;
|
||||
import com.jeesite.common.ueditor.define.BaseState;
|
||||
import com.jeesite.common.ueditor.define.FileType;
|
||||
import com.jeesite.common.ueditor.define.State;
|
||||
|
||||
import net.coobird.thumbnailator.Thumbnails;
|
||||
import net.coobird.thumbnailator.Thumbnails.Builder;
|
||||
|
||||
public class BinaryUploader {
|
||||
|
||||
public static final State save(HttpServletRequest request,
|
||||
Map<String, Object> conf) {
|
||||
FileItemStream fileStream = null; // 原始上传
|
||||
MultipartFile fileStream2 = null; // Spring MVC 上传
|
||||
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) {
|
||||
// 原始上传无文件,则检查是否是Spring MVC上传 ThinkGem
|
||||
MultipartFile file = null;
|
||||
if (request instanceof MultipartHttpServletRequest){
|
||||
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
|
||||
Iterator<String> it = multiRequest.getFileNames();
|
||||
while (it.hasNext()) {
|
||||
file = multiRequest.getFile(it.next());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (file != null && !file.isEmpty() && file.getOriginalFilename() != null) {
|
||||
fileStream2 = file;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileStream == null && fileStream2 == null) {
|
||||
return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
|
||||
}
|
||||
|
||||
String savePath = (String) conf.get("savePath");
|
||||
String originFileName = fileStream != null ? fileStream.getName() : fileStream2.getOriginalFilename();
|
||||
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 = FileUtils.path((String) conf.get("rootPath") + savePath);
|
||||
|
||||
InputStream is = fileStream != null ? fileStream.openStream() : fileStream2.getInputStream();
|
||||
State storageState = StorageManager.saveFileByInputStream(is, physicalPath, maxSize);
|
||||
is.close();
|
||||
|
||||
if (storageState.isSuccess()) {
|
||||
int actionCode = ((Integer) conf.get("actionCode")).intValue();
|
||||
String ctx = request.getContextPath(); // ThinkGem 修正上传图片后返回无contextpath问题
|
||||
|
||||
// 上传图片后,进行图片压缩
|
||||
if (actionCode == ActionMap.UPLOAD_IMAGE){
|
||||
|
||||
// 如果开启了压缩图片
|
||||
if ((Boolean)conf.get("imageCompressEnable")){
|
||||
Integer width = (Integer)conf.get("imageCompressBorder");
|
||||
// 过滤掉gif图片,因为gif图片转换后会出现黑色背景的情况(gif基本也没有比较大的图片)。
|
||||
if (StringUtils.inString(FileUtils.getFileExtension(physicalPath),
|
||||
"png","jpg","jpeg","bmp","ico")){
|
||||
Builder<File> file = Thumbnails.of(physicalPath);
|
||||
BufferedImage bufferedImage = ImageIO.read(new File(physicalPath));
|
||||
if (bufferedImage != null){
|
||||
if (bufferedImage.getWidth() <= width){
|
||||
file.width(bufferedImage.getWidth());
|
||||
}else{
|
||||
file.width(width);
|
||||
}
|
||||
file.toFile(physicalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 上传成功后 转换格式 按照新的视频格式 返回前台 ThinkGem
|
||||
else if(actionCode == ActionMap.UPLOAD_VIDEO){
|
||||
final VideoUtils v = new VideoUtils(physicalPath);
|
||||
// 先截图
|
||||
if (v.cutPic()){
|
||||
// 开启进程,在转换视频文件
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
v.convert();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
storageState.putInfo("url", ctx + PathFormat.format(savePath) + "." + v.getOutputFileExtension());
|
||||
storageState.putInfo("type", "." + v.getOutputFileExtension());
|
||||
storageState.putInfo("original", originFileName +"."+ v.getInputFileExtension());
|
||||
return storageState;
|
||||
}
|
||||
}
|
||||
storageState.putInfo("url", ctx + 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package com.jeesite.common.ueditor.upload;
|
||||
|
||||
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 com.jeesite.common.idgen.IdGenerate;
|
||||
import com.jeesite.common.io.FileUtils;
|
||||
import com.jeesite.common.io.PropertiesUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.ueditor.define.AppInfo;
|
||||
import com.jeesite.common.ueditor.define.BaseState;
|
||||
import com.jeesite.common.ueditor.define.State;
|
||||
|
||||
public class StorageManager {
|
||||
|
||||
public static final int BUFFER_SIZE = 8192;
|
||||
|
||||
public StorageManager() {
|
||||
|
||||
}
|
||||
|
||||
public static State saveBinaryFile(byte[] data, String path) {
|
||||
File file = new File(path);
|
||||
|
||||
State state = valid(file);
|
||||
|
||||
if (!state.isSuccess()) {
|
||||
return state;
|
||||
}
|
||||
|
||||
BufferedOutputStream bos = null;
|
||||
try {
|
||||
bos = new BufferedOutputStream(new FileOutputStream(file));
|
||||
bos.write(data);
|
||||
} catch (IOException ioe) {
|
||||
return new BaseState(false, AppInfo.IO_ERROR);
|
||||
}finally {
|
||||
if (bos != null){
|
||||
try {
|
||||
bos.flush();
|
||||
bos.close();
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 验证允许的上传的文件类型(如果没有设置则不验证,默认不设置)
|
||||
String allowContentTypes = PropertiesUtils.getInstance()
|
||||
.getProperty("file.allowContentTypes");
|
||||
if(StringUtils.isNotBlank(allowContentTypes)){
|
||||
String rct = FileUtils.getRealContentType(file);
|
||||
if (!StringUtils.inString(rct, allowContentTypes.split(","))){
|
||||
file.delete();
|
||||
return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
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, StorageManager.BUFFER_SIZE);
|
||||
|
||||
BufferedOutputStream bos = null;
|
||||
try {
|
||||
try{
|
||||
bos = new BufferedOutputStream(
|
||||
new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
|
||||
int count = 0;
|
||||
while ((count = bis.read(dataBuf)) != -1) {
|
||||
bos.write(dataBuf, 0, count);
|
||||
}
|
||||
}finally {
|
||||
if (bos != null){
|
||||
bos.flush();
|
||||
bos.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpFile.length() > maxSize) {
|
||||
tmpFile.delete();
|
||||
return new BaseState(false, AppInfo.MAX_SIZE);
|
||||
}
|
||||
|
||||
// 验证允许的上传的文件类型(如果没有设置则不验证,默认不设置)
|
||||
String allowContentTypes = PropertiesUtils.getInstance()
|
||||
.getProperty("file.allowContentTypes");
|
||||
if(StringUtils.isNotBlank(allowContentTypes)){
|
||||
String rct = FileUtils.getRealContentType(tmpFile);
|
||||
if (!StringUtils.inString(rct, allowContentTypes.split(","))){
|
||||
tmpFile.delete();
|
||||
return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
state = saveTmpFile(tmpFile, path);
|
||||
|
||||
if (!state.isSuccess()) {
|
||||
tmpFile.delete();
|
||||
}
|
||||
|
||||
return state;
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}finally {
|
||||
if (bis != null){
|
||||
try {
|
||||
bis.close();
|
||||
} 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, StorageManager.BUFFER_SIZE);
|
||||
|
||||
try {
|
||||
BufferedOutputStream bos = null;
|
||||
try{
|
||||
bos = new BufferedOutputStream(new FileOutputStream(tmpFile),
|
||||
StorageManager.BUFFER_SIZE);
|
||||
int count = 0;
|
||||
while ((count = bis.read(dataBuf)) != -1) {
|
||||
bos.write(dataBuf, 0, count);
|
||||
}
|
||||
}finally {
|
||||
if (bos != null){
|
||||
bos.flush();
|
||||
bos.close();
|
||||
}
|
||||
}
|
||||
state = saveTmpFile(tmpFile, path);
|
||||
if (!state.isSuccess()) {
|
||||
tmpFile.delete();
|
||||
}
|
||||
return state;
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}finally {
|
||||
if (bis != null){
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new BaseState(false, AppInfo.IO_ERROR);
|
||||
}
|
||||
|
||||
private static File getTmpFile() {
|
||||
// File tmpDir = FileUtils.getTempDirectory();
|
||||
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
|
||||
// String tmpFileName = (Math.random() * 10000 + "").replace(".", "");
|
||||
// return new File(tmpDir, tmpFileName);
|
||||
return new File(tmpDir, IdGenerate.randomBase62(10));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.jeesite.common.ueditor.upload;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.jeesite.common.ueditor.define.State;
|
||||
|
||||
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, this.request.getParameter(filedName),
|
||||
this.conf);
|
||||
} else {
|
||||
state = BinaryUploader.save(this.request, this.conf);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
package com.jeesite.common.utils.excel;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -13,8 +14,10 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -36,6 +39,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.collect.SetUtils;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.reflect.ReflectUtils;
|
||||
@@ -47,9 +51,9 @@ import com.jeesite.common.utils.excel.annotation.ExcelFields;
|
||||
/**
|
||||
* 导出Excel文件(导出“XLSX”格式,支持大数据量导出 @see org.apache.poi.ss.SpreadsheetVersion)
|
||||
* @author ThinkGem
|
||||
* @version 2013-04-21
|
||||
* @version 2018-08-11
|
||||
*/
|
||||
public class ExcelExport {
|
||||
public class ExcelExport implements Closeable{
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(ExcelExport.class);
|
||||
|
||||
@@ -76,7 +80,12 @@ public class ExcelExport {
|
||||
/**
|
||||
* 注解列表(Object[]{ ExcelField, Field/Method })
|
||||
*/
|
||||
List<Object[]> annotationList;
|
||||
private List<Object[]> annotationList;
|
||||
|
||||
/**
|
||||
* 用于清理缓存
|
||||
*/
|
||||
private Set<Class<?>> fieldTypes = SetUtils.newHashSet();
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
@@ -240,7 +249,7 @@ public class ExcelExport {
|
||||
// 创建工作表
|
||||
this.createSheet(sheetName, title, headerList, headerWidthList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加到 annotationList
|
||||
*/
|
||||
@@ -266,7 +275,7 @@ public class ExcelExport {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建工作表
|
||||
* @param sheetName 指定Sheet名称
|
||||
@@ -431,6 +440,7 @@ public class ExcelExport {
|
||||
if(val == null){
|
||||
cell.setCellValue("");
|
||||
}else if(fieldType != Class.class){
|
||||
fieldTypes.add(fieldType); // 先存起来,方便完成后清理缓存
|
||||
cell.setCellValue((String)fieldType.getMethod("setValue", Object.class).invoke(null, val));
|
||||
try{
|
||||
defaultDataFormat = (String)fieldType.getMethod("getDataFormat").invoke(null);
|
||||
@@ -456,8 +466,11 @@ public class ExcelExport {
|
||||
cell.setCellValue((Date) val);
|
||||
defaultDataFormat = "yyyy-MM-dd HH:mm";
|
||||
}else {
|
||||
cell.setCellValue((String)Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
|
||||
"fieldtype."+val.getClass().getSimpleName()+"Type")).getMethod("setValue", Object.class).invoke(null, val));
|
||||
// 如果没有指定 fieldType,切自行根据类型查找相应的转换类(com.jeesite.common.utils.excel.fieldtype.值的类名+Type)
|
||||
Class<?> fieldType2 = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
|
||||
"fieldtype."+val.getClass().getSimpleName()+"Type"));
|
||||
fieldTypes.add(fieldType2); // 先存起来,方便完成后清理缓存
|
||||
cell.setCellValue((String)fieldType2.getMethod("setValue", Object.class).invoke(null, val));
|
||||
}
|
||||
}
|
||||
// if (val != null){
|
||||
@@ -574,12 +587,31 @@ public class ExcelExport {
|
||||
|
||||
/**
|
||||
* 清理临时文件
|
||||
* @deprecated see close()
|
||||
*/
|
||||
public ExcelExport dispose(){
|
||||
try {
|
||||
this.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (wb instanceof SXSSFWorkbook){
|
||||
((SXSSFWorkbook)wb).dispose();
|
||||
}
|
||||
return this;
|
||||
Iterator<Class<?>> it = fieldTypes.iterator();
|
||||
while(it.hasNext()){
|
||||
Class<?> clazz = it.next();
|
||||
try {
|
||||
clazz.getMethod("clearCache").invoke(null);
|
||||
} catch (Exception e) {
|
||||
// 报错忽略,有可能没实现此方法
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
package com.jeesite.common.utils.excel;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -15,6 +16,7 @@ import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
@@ -34,6 +36,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.jeesite.common.callback.MethodCallback;
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.collect.SetUtils;
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
@@ -45,9 +48,9 @@ import com.jeesite.common.utils.excel.annotation.ExcelFields;
|
||||
/**
|
||||
* 导入Excel文件(支持“XLS”和“XLSX”格式)
|
||||
* @author ThinkGem
|
||||
* @version 2014-8-19
|
||||
* @version 2018-08-11
|
||||
*/
|
||||
public class ExcelImport {
|
||||
public class ExcelImport implements Closeable {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(ExcelImport.class);
|
||||
|
||||
@@ -66,6 +69,11 @@ public class ExcelImport {
|
||||
*/
|
||||
private int headerNum;
|
||||
|
||||
/**
|
||||
* 用于清理缓存
|
||||
*/
|
||||
private Set<Class<?>> fieldTypes = SetUtils.newHashSet();
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param path 导入文件对象,读取第一个工作表
|
||||
@@ -416,34 +424,45 @@ public class ExcelImport {
|
||||
}
|
||||
//log.debug("Import value type: ["+i+","+column+"] " + valType);
|
||||
try {
|
||||
if (val != null){
|
||||
if (valType == String.class){
|
||||
String s = String.valueOf(val.toString());
|
||||
if(StringUtils.endsWith(s, ".0")){
|
||||
val = StringUtils.substringBefore(s, ".0");
|
||||
if (StringUtils.isNotBlank(ef.attrName())){
|
||||
if (ef.fieldType() != Class.class){
|
||||
fieldTypes.add(ef.fieldType()); // 先存起来,方便完成后清理缓存
|
||||
val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val);
|
||||
}
|
||||
}else{
|
||||
if (val != null){
|
||||
if (valType == String.class){
|
||||
String s = String.valueOf(val.toString());
|
||||
if(StringUtils.endsWith(s, ".0")){
|
||||
val = StringUtils.substringBefore(s, ".0");
|
||||
}else{
|
||||
val = String.valueOf(val.toString());
|
||||
}
|
||||
}else if (valType == Integer.class){
|
||||
val = Double.valueOf(val.toString()).intValue();
|
||||
}else if (valType == Long.class){
|
||||
val = Double.valueOf(val.toString()).longValue();
|
||||
}else if (valType == Double.class){
|
||||
val = Double.valueOf(val.toString());
|
||||
}else if (valType == Float.class){
|
||||
val = Float.valueOf(val.toString());
|
||||
}else if (valType == Date.class){
|
||||
if (val instanceof String){
|
||||
val = DateUtils.parseDate(val);
|
||||
}else if (val instanceof Double){
|
||||
val = DateUtil.getJavaDate((Double)val); // POI Excel 日期格式转换
|
||||
}
|
||||
}else{
|
||||
val = String.valueOf(val.toString());
|
||||
}
|
||||
}else if (valType == Integer.class){
|
||||
val = Double.valueOf(val.toString()).intValue();
|
||||
}else if (valType == Long.class){
|
||||
val = Double.valueOf(val.toString()).longValue();
|
||||
}else if (valType == Double.class){
|
||||
val = Double.valueOf(val.toString());
|
||||
}else if (valType == Float.class){
|
||||
val = Float.valueOf(val.toString());
|
||||
}else if (valType == Date.class){
|
||||
if (val instanceof String){
|
||||
val = DateUtils.parseDate(val);
|
||||
}else if (val instanceof Double){
|
||||
val = DateUtil.getJavaDate((Double)val); // POI Excel 日期格式转换
|
||||
}
|
||||
}else{
|
||||
if (ef.fieldType() != Class.class){
|
||||
val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
|
||||
}else{
|
||||
val = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
|
||||
"fieldtype."+valType.getSimpleName()+"Type")).getMethod("getValue", String.class).invoke(null, val.toString());
|
||||
if (ef.fieldType() != Class.class){
|
||||
fieldTypes.add(ef.fieldType()); // 先存起来,方便完成后清理缓存
|
||||
val = ef.fieldType().getMethod("getValue", String.class).invoke(null, val.toString());
|
||||
}else{
|
||||
// 如果没有指定 fieldType,切自行根据类型查找相应的转换类(com.jeesite.common.utils.excel.fieldtype.值的类名+Type)
|
||||
Class<?> fieldType2 = Class.forName(this.getClass().getName().replaceAll(this.getClass().getSimpleName(),
|
||||
"fieldtype."+valType.getSimpleName()+"Type"));
|
||||
fieldTypes.add(fieldType2); // 先存起来,方便完成后清理缓存
|
||||
val = fieldType2.getMethod("getValue", String.class).invoke(null, val.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,14 +473,18 @@ public class ExcelImport {
|
||||
exceptionCallback.execute(ex, i, column);
|
||||
}
|
||||
// set entity value
|
||||
if (os[1] instanceof Field){
|
||||
ReflectUtils.invokeSetter(e, ((Field)os[1]).getName(), val);
|
||||
}else if (os[1] instanceof Method){
|
||||
String mthodName = ((Method)os[1]).getName();
|
||||
if ("get".equals(mthodName.substring(0, 3))){
|
||||
mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
|
||||
if (StringUtils.isNotBlank(ef.attrName())){
|
||||
ReflectUtils.invokeSetter(e, ef.attrName(), val);
|
||||
}else{
|
||||
if (os[1] instanceof Field){
|
||||
ReflectUtils.invokeSetter(e, ((Field)os[1]).getName(), val);
|
||||
}else if (os[1] instanceof Method){
|
||||
String mthodName = ((Method)os[1]).getName();
|
||||
if ("get".equals(mthodName.substring(0, 3))){
|
||||
mthodName = "set"+StringUtils.substringAfter(mthodName, "get");
|
||||
}
|
||||
ReflectUtils.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
|
||||
}
|
||||
ReflectUtils.invokeMethod(e, mthodName, new Class[] {valType}, new Object[] {val});
|
||||
}
|
||||
}
|
||||
sb.append(val+", ");
|
||||
@@ -471,6 +494,19 @@ public class ExcelImport {
|
||||
}
|
||||
return dataList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Iterator<Class<?>> it = fieldTypes.iterator();
|
||||
while(it.hasNext()){
|
||||
Class<?> clazz = it.next();
|
||||
try {
|
||||
clazz.getMethod("clearCache").invoke(null);
|
||||
} catch (Exception e) {
|
||||
// 报错忽略,有可能没实现此方法
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 导入测试
|
||||
|
||||
@@ -37,4 +37,11 @@ public class MoneyType {
|
||||
return "0.00";
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
public static void clearCache(){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -78,6 +78,21 @@ public class ServletUtils {
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持AJAX的页面跳转
|
||||
*/
|
||||
public static void redirectUrl(HttpServletRequest request, HttpServletResponse response, String url){
|
||||
try {
|
||||
if (ServletUtils.isAjaxRequest(request)){
|
||||
request.getRequestDispatcher(url).forward(request, response); // AJAX不支持Redirect改用Forward
|
||||
}else{
|
||||
response.sendRedirect(request.getContextPath() + url);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是Ajax异步请求
|
||||
* @param request
|
||||
@@ -173,9 +188,10 @@ public class ServletUtils {
|
||||
resultMap.put("data", data);
|
||||
}
|
||||
}
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
HttpServletRequest request = getRequest();
|
||||
String uri = request.getRequestURI();
|
||||
if (StringUtils.endsWithIgnoreCase(uri, ".xml")){
|
||||
if (StringUtils.endsWithIgnoreCase(uri, ".xml") || StringUtils
|
||||
.equalsIgnoreCase(request.getParameter("__ajax"), "xml")){
|
||||
return XmlMapper.toXml(resultMap);
|
||||
}else{
|
||||
String functionName = request.getParameter("__callback");
|
||||
@@ -202,7 +218,7 @@ public class ServletUtils {
|
||||
/**
|
||||
* 直接将结果JSON字符串渲染到客户端(支持JsonP,请求参数加:__callback=回调函数名)
|
||||
* @param response 渲染对象:{result:'true',message:'',data:{}}
|
||||
* @param result Global.TRUE or Globle.False
|
||||
* @param result 结果标识:Global.TRUE or Globle.False
|
||||
* @param message 执行消息
|
||||
* @param data 消息数据
|
||||
* @return null
|
||||
@@ -212,16 +228,18 @@ public class ServletUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为JSON字符串渲染到客户端(支持JsonP,请求参数加:__callback=回调函数名)
|
||||
* 将对象转换为JSON、XML、JSONP字符串渲染到客户端(JsonP,请求参数加:__callback=回调函数名)
|
||||
* @param request 请求对象,用来得到输出格式的指令:JSON、XML、JSONP
|
||||
* @param response 渲染对象
|
||||
* @param object 待转换JSON并渲染的对象
|
||||
* @return null
|
||||
*/
|
||||
public static String renderObject(HttpServletResponse response, Object object) {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
HttpServletRequest request = getRequest();
|
||||
String uri = request.getRequestURI();
|
||||
if (StringUtils.endsWithIgnoreCase(uri, ".xml")){
|
||||
return XmlMapper.toXml(object);
|
||||
if (StringUtils.endsWithIgnoreCase(uri, ".xml") || StringUtils
|
||||
.equalsIgnoreCase(request.getParameter("__ajax"), "xml")){
|
||||
return renderString(response, XmlMapper.toXml(object));
|
||||
}else{
|
||||
String functionName = request.getParameter("__callback");
|
||||
if (StringUtils.isNotBlank(functionName)){
|
||||
@@ -250,8 +268,18 @@ public class ServletUtils {
|
||||
*/
|
||||
public static String renderString(HttpServletResponse response, String string, String type) {
|
||||
try {
|
||||
// response.reset(); // 先注释掉,否则以前设置的Header会被清理掉,如ajax登录设置记住我Cookie
|
||||
response.setContentType(type == null ? "application/json" : type);
|
||||
// response.reset(); // 注释掉,否则以前设置的Header会被清理掉,如ajax登录设置记住我的Cookie信息
|
||||
if (type == null){
|
||||
if ((StringUtils.startsWith(string, "{") && StringUtils.endsWith(string, "}"))
|
||||
|| (StringUtils.startsWith(string, "[") && StringUtils.endsWith(string, "]"))){
|
||||
type = "application/json";
|
||||
}else if (StringUtils.startsWith(string, "<") && StringUtils.endsWith(string, ">")){
|
||||
type = "application/xml";
|
||||
}else{
|
||||
type = "text/html";
|
||||
}
|
||||
}
|
||||
response.setContentType(type);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.getWriter().print(string);
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Skin: Black
|
||||
* ----------
|
||||
*/
|
||||
.main-header .navbar {
|
||||
background-color: #303643;
|
||||
}
|
||||
.main-header .navbar .nav > li > a {
|
||||
color: #eaeaea;
|
||||
}
|
||||
.main-header .navbar .nav > li > a:hover,
|
||||
.main-header .navbar .nav > li > a:active,
|
||||
.main-header .navbar .nav > li > a:focus,
|
||||
.main-header .navbar .nav .open > a,
|
||||
.main-header .navbar .nav .open > a:hover,
|
||||
.main-header .navbar .nav .open > a:focus,
|
||||
.main-header .navbar .nav > .active > a {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #f6f6f6;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle {
|
||||
color: #ffffff;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle {
|
||||
color: #fff;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle:hover {
|
||||
background-color: #367fa9;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.main-header .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.main-header .navbar .dropdown-menu li a {
|
||||
color: #fff;
|
||||
}
|
||||
.main-header .navbar .dropdown-menu li a:hover {
|
||||
background: #367fa9;
|
||||
}
|
||||
}
|
||||
.main-header .logo {
|
||||
/* background-color: #2A579A; */
|
||||
color: #f6f6f6;
|
||||
border-bottom: 0 solid transparent;
|
||||
}
|
||||
.main-header .logo:hover {
|
||||
/* background-color: #204F93; */
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.main-header li.user-header {
|
||||
background-color: #2A579A;
|
||||
}
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #E3E7EC;
|
||||
}
|
||||
.content-wrapper,
|
||||
.main-footer {
|
||||
border-left: 1px solid #d2d6de;
|
||||
}
|
||||
.user-panel > .info,
|
||||
.user-panel > .info > a {
|
||||
color: #555;
|
||||
}
|
||||
.sidebar-menu > li {
|
||||
-webkit-transition: border-left-color 0.3s ease;
|
||||
-o-transition: border-left-color 0.3s ease;
|
||||
transition: border-left-color 0.3s ease;
|
||||
}
|
||||
.sidebar-menu > li.header {
|
||||
color: #848484;
|
||||
background: #E3E7EC;
|
||||
}
|
||||
.sidebar-menu > li > a {
|
||||
border-left: 3px solid transparent;
|
||||
font-weight: 600;
|
||||
}
|
||||
.sidebar-menu > li:hover > a,
|
||||
.sidebar-menu > li.active > a {
|
||||
color: #000;
|
||||
background: #EAEDF1;
|
||||
}
|
||||
.sidebar-menu > li.active {
|
||||
border-left-color: #2A579A;
|
||||
}
|
||||
.sidebar-menu > li.active > a {
|
||||
font-weight: 600;
|
||||
}
|
||||
.sidebar-menu > li.menu-open > a,
|
||||
.sidebar-menu > li > .treeview-menu {
|
||||
background: #EAEDF1;
|
||||
}
|
||||
.sidebar a {
|
||||
color: #555;
|
||||
}
|
||||
.sidebar a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.treeview-menu > li > a {
|
||||
color: #555;
|
||||
}
|
||||
.treeview-menu > li.active > a,
|
||||
.treeview-menu > li > a:hover {
|
||||
color: #000;
|
||||
}
|
||||
.sidebar-form {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #d2d6de;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
.sidebar-form input[type="text"],
|
||||
.sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #fff;
|
||||
border: 1px solid transparent;
|
||||
height: 35px;
|
||||
}
|
||||
.sidebar-form input[type="text"] {
|
||||
color: #666;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px;
|
||||
}
|
||||
.sidebar-form input[type="text"]:focus,
|
||||
.sidebar-form input[type="text"]:focus + .input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666;
|
||||
}
|
||||
.sidebar-form input[type="text"]:focus + .input-group-btn .btn {
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
.main-footer {
|
||||
border-top-color: #d2d6de;
|
||||
}
|
||||
.skin-blue.layout-top-nav .main-header > .logo {
|
||||
background-color: #2A579A;
|
||||
color: #ffffff;
|
||||
border-bottom: 0 solid transparent;
|
||||
}
|
||||
.skin-blue.layout-top-nav .main-header > .logo:hover {
|
||||
background-color: #3b8ab8;
|
||||
}
|
||||
|
||||
.sidebar-menu .treeview-item.active > a {color:#000;background-color:#fff;}
|
||||
@@ -76,7 +76,6 @@
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
.wrapper,
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #263238;
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Skin: Black
|
||||
* ----------
|
||||
*/
|
||||
.main-header .navbar {
|
||||
background-color: #263238;
|
||||
}
|
||||
.main-header .navbar .nav > li > a {
|
||||
color: #eaeaea;
|
||||
}
|
||||
.main-header .navbar .nav > li > a:hover,
|
||||
.main-header .navbar .nav > li > a:active,
|
||||
.main-header .navbar .nav > li > a:focus,
|
||||
.main-header .navbar .nav .open > a,
|
||||
.main-header .navbar .nav .open > a:hover,
|
||||
.main-header .navbar .nav .open > a:focus,
|
||||
.main-header .navbar .nav > .active > a {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
color: #f6f6f6;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle {
|
||||
color: #ffffff;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle {
|
||||
color: #fff;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle:hover {
|
||||
background-color: #367fa9;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.main-header .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.main-header .navbar .dropdown-menu li a {
|
||||
color: #fff;
|
||||
}
|
||||
.main-header .navbar .dropdown-menu li a:hover {
|
||||
background: #367fa9;
|
||||
}
|
||||
}
|
||||
.main-header .logo {
|
||||
/* background-color: #367fa9; */
|
||||
color: #f6f6f6;
|
||||
border-bottom: 0 solid transparent;
|
||||
}
|
||||
.main-header .logo:hover {
|
||||
/* background-color: #357ca5; */
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.main-header li.user-header {
|
||||
background-color: #3c8dbc;
|
||||
}
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #263238;
|
||||
}
|
||||
.user-panel > .info,
|
||||
.user-panel > .info > a {
|
||||
color: #fff;
|
||||
}
|
||||
.sidebar-menu > li.header {
|
||||
color: #4b646f;
|
||||
background: #1a2226;
|
||||
}
|
||||
.sidebar-menu > li > a {
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
.sidebar-menu > li:hover > a,
|
||||
.sidebar-menu > li.active > a {
|
||||
color: #ffffff;
|
||||
background: #2c3b41;
|
||||
/* border-left-color: #3c8dbc; */
|
||||
}
|
||||
.sidebar-menu > li.menu-open > a,
|
||||
.sidebar-menu > li > .treeview-menu {
|
||||
background: #2c3b41;
|
||||
}
|
||||
.sidebar a {
|
||||
color: #eaeaea;
|
||||
}
|
||||
.sidebar a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.treeview-menu > li > a {
|
||||
color: #c7d0da;
|
||||
}
|
||||
.treeview-menu > li.active > a,
|
||||
.treeview-menu > li > a:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
.sidebar-form {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #374850;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
.sidebar-form input[type="text"],
|
||||
.sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #374850;
|
||||
border: 1px solid transparent;
|
||||
height: 35px;
|
||||
}
|
||||
.sidebar-form input[type="text"] {
|
||||
color: #666;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px;
|
||||
}
|
||||
.sidebar-form input[type="text"]:focus,
|
||||
.sidebar-form input[type="text"]:focus + .input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666;
|
||||
}
|
||||
.sidebar-form input[type="text"]:focus + .input-group-btn .btn {
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
.skin-blue.layout-top-nav .main-header > .logo {
|
||||
background-color: #3c8dbc;
|
||||
color: #ffffff;
|
||||
border-bottom: 0 solid transparent;
|
||||
}
|
||||
.skin-blue.layout-top-nav .main-header > .logo:hover {
|
||||
background-color: #3b8ab8;
|
||||
}
|
||||
|
||||
.sidebar-menu .treeview-item.active > a {color:#fff;background-color:#3c8dbc;}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* http://jeesite.com
|
||||
*/
|
||||
a, a:hover, a:active, a:focus, .form-unit, th[aria-selected=true] .ui-jqgrid-sortable {
|
||||
color:#1890ff;
|
||||
}
|
||||
.main-header .navbar {
|
||||
background-color: #1890ff;
|
||||
}
|
||||
.main-header .navbar .nav > li > a {
|
||||
color: #ffffff;
|
||||
}
|
||||
.main-header .navbar .nav > li > a:hover,
|
||||
.main-header .navbar .nav > li > a:active,
|
||||
.main-header .navbar .nav > li > a:focus,
|
||||
.main-header .navbar .nav .open > a,
|
||||
.main-header .navbar .nav .open > a:hover,
|
||||
.main-header .navbar .nav .open > a:focus,
|
||||
.main-header .navbar .nav > .active > a {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #f6f6f6;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle {
|
||||
color: #ffffff;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle {
|
||||
color: #fff;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle:hover {
|
||||
background-color: #367fa9;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.main-header .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.main-header .navbar .dropdown-menu li a {
|
||||
color: #fff;
|
||||
}
|
||||
.main-header .navbar .dropdown-menu li a:hover {
|
||||
background: #367fa9;
|
||||
}
|
||||
}
|
||||
.main-header .logo {
|
||||
background-color: #1890ff;
|
||||
color: #ffffff;
|
||||
border-bottom: 0 solid transparent;
|
||||
}
|
||||
.main-header .logo:hover {
|
||||
background-color: #1890ff;
|
||||
}
|
||||
.main-header li.user-header {
|
||||
background-color: #1890ff;
|
||||
}
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.content-wrapper,
|
||||
.main-footer {
|
||||
border-left: 1px solid #eeeeee;
|
||||
}
|
||||
.user-panel > .info,
|
||||
.user-panel > .info > a {
|
||||
color: #555;
|
||||
}
|
||||
.sidebar-menu > li {
|
||||
-webkit-transition: border-left-color 0.3s ease;
|
||||
-o-transition: border-left-color 0.3s ease;
|
||||
transition: border-left-color 0.3s ease;
|
||||
}
|
||||
.sidebar-menu > li.header {
|
||||
color: #848484;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
.sidebar-menu > li > a {
|
||||
border-left: 3px solid transparent;
|
||||
font-weight: 600;
|
||||
}
|
||||
.sidebar-menu > li:hover > a,
|
||||
.sidebar-menu > li.active > a {
|
||||
color: #000;
|
||||
background: #ffffff;
|
||||
}
|
||||
.sidebar-menu > li.active {
|
||||
border-left-color: #1890ff;
|
||||
}
|
||||
.sidebar-menu > li.active > a {
|
||||
font-weight: 600;
|
||||
}
|
||||
.sidebar-menu > li.menu-open > a,
|
||||
.sidebar-menu > li > .treeview-menu {
|
||||
background: #ffffff;
|
||||
}
|
||||
.sidebar a {
|
||||
color: #555;
|
||||
}
|
||||
.sidebar a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.treeview-menu > li > a {
|
||||
color: #555;
|
||||
}
|
||||
.treeview-menu > li.active > a,
|
||||
.treeview-menu > li > a:hover {
|
||||
color: #000;
|
||||
}
|
||||
.sidebar-form {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #d2d6de;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
.sidebar-form input[type="text"],
|
||||
.sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #fff;
|
||||
border: 1px solid transparent;
|
||||
height: 35px;
|
||||
}
|
||||
.sidebar-form input[type="text"] {
|
||||
color: #666;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px;
|
||||
}
|
||||
.sidebar-form input[type="text"]:focus,
|
||||
.sidebar-form input[type="text"]:focus + .input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666;
|
||||
}
|
||||
.sidebar-form input[type="text"]:focus + .input-group-btn .btn {
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
.main-footer {
|
||||
border-top-color: #d2d6de;
|
||||
}
|
||||
.skin-blue.layout-top-nav .main-header > .logo {
|
||||
background-color: #1890ff;
|
||||
color: #ffffff;
|
||||
border-bottom: 0 solid transparent;
|
||||
}
|
||||
.skin-blue.layout-top-nav .main-header > .logo:hover {
|
||||
background-color: #3b8ab8;
|
||||
}
|
||||
|
||||
.sidebar-menu .treeview-item.active > a {color:#1890ff;background-color:#e1f1ff;border-right:solid #57a6ee;}
|
||||
|
||||
.content-wrapper, .right-side, body {background-color:#f8f8f8;}
|
||||
|
||||
.btn-primary, .btn-primary:hover, .btn-primary:active,
|
||||
.btn-primary.hover, .btn-primary.focus, .btn-primary:focus,
|
||||
.btn-primary.active.focus, .btn-primary.active:focus, .btn-primary.active:hover,
|
||||
.btn-primary:active.focus, .btn-primary:active:focus, .btn-primary:active:hover,
|
||||
.open>.dropdown-toggle.btn-primary.focus, .open>.dropdown-toggle.btn-primary:focus,
|
||||
.open>.dropdown-toggle.btn-primary:hover, .layui-layer-btn .layui-layer-btn0,
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice,
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected],
|
||||
.wup_container .placeholder .webuploader-pick {background-color:#1890ff!important;border-color:#1890ff;}
|
||||
.form-unit, th[aria-selected=true] .ui-jqgrid-sortable {color:#1890ff;}
|
||||
.form-unit {border-bottom: 1px solid #eee;}
|
||||
|
||||
.tabpanel_mover li {padding:1px 16px 2px 3px;margin:6px 0 6px 6px;border:1px solid #e4e4e4;
|
||||
border-radius:3px;background:#fff;box-shadow:0 0 5px #e6e6e6;}
|
||||
.tabpanel_mover li.active {background-color:#3aa0ff;}
|
||||
.tabpanel_mover li.active div {color:#fff;}
|
||||
.tabpanel_mover li .closer {font:11px/1 FontAwesome;top:6px;right:2px;background:none;opacity:0.7;}
|
||||
.tabpanel_mover li .closer:before {content:"\f00d";}
|
||||
.tabpanel_mover li .closer:hover {background:none;-moz-transform: scale(1.2);-webkit-transform: scale(1.2);
|
||||
-o-transform: scale(1.2);-ms-transform: scale(1.2);transform: scale(1.2);color:#d30606;}
|
||||
.tabpanel_mover li.active .closer:hover {color:#fff;opacity:0.9;}
|
||||
.tabpanel_tab_content {background-color:#fafafa;border-bottom-color:#eeeeee;overflow:visible;}
|
||||
/* .tabpanel_mover li {background:#fff;border-right:1px solid #eee;padding:8px 16px 8px 5px;}
|
||||
.tabpanel_mover li.active {background-color:#fff;border-bottom:3px solid #3aa0ff;}
|
||||
.tabpanel_mover li.active div {color:#0975d9;}
|
||||
.tabpanel_mover li .closer {background:none;font:11px/1 FontAwesome;opacity:0.7;}
|
||||
.tabpanel_mover li .closer:before {content:"\f00d";}
|
||||
.tabpanel_mover li .closer:hover {background:none;-moz-transform: scale(1.2);-webkit-transform: scale(1.2);
|
||||
-o-transform: scale(1.2);-ms-transform: scale(1.2);transform: scale(1.2);color:#d30606;}
|
||||
.tabpanel_tab_content {background-color:#fafafa;border-bottom-color:#eeeeee;overflow:visible;} 替换上面 tab 样式,改变 tab 风格。*/
|
||||
|
||||
/* .main-content {padding:10px;}
|
||||
.ui-layout-container {padding:10px;}
|
||||
.ui-layout-resizer {background:transparent;}
|
||||
.ui-layout-pane {box-shadow:0 0 5px #e0e0e0;}
|
||||
.ui-layout-pane>.main-content {padding:0;}
|
||||
.ui-layout-content>.wrapper>.main-content {padding:0;}
|
||||
.box-main,.nav-main{border-radius:3px;box-shadow:0 0 5px #e0e0e0;} 解开注释,可给内容页面,添加内边距样式 */
|
||||
.box-main>.box-header {border-bottom-color:#eeeeee;}
|
||||
.box-main>.box-header .box-title .fa {color:#1890ff;}
|
||||
.nav-tabs-custom>.nav-tabs>li.active {border-top-color:#3aa0ff;}
|
||||
.form-control:focus,.select2-container--default.select2-container--focus .select2-selection--multiple,
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {border-color:#66afe9!important;}
|
||||
.table thead tr, .ui-jqgrid-htable thead tr, .ui-jqgrid-hdiv, .ui-jqgrid-hbox {background-color:#f6f6f6;}
|
||||
.ui-jqgrid .ui-jqgrid-htable th.ui-th-column-header, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column,
|
||||
.ui-jqgrid .ui-jqgrid-labels th, .ui-jqgrid .ui-widget-content, .ui-jqgrid tr.ui-row-ltr td,
|
||||
.ui-jqgrid tr.ui-row-rtl td, .ui-jqgrid tr.ui-row-ltr td:last-child {border-color:#eaeaea;}
|
||||
.ui-state-hover td, .ui-widget-content .ui-state-hover td, .ui-widget-header .ui-state-hover td,
|
||||
.ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {background:#f5f5f5;}
|
||||
.ui-jqgrid tr.ui-state-highlight.ui-row-ltr td {background-color:#e5f3ff;}
|
||||
/* .ui-jqgrid tr.ui-row-ltr td {border-right:0!important;} 解开注释,可去除表格单元格的竖边框线 */
|
||||
@@ -56,7 +56,6 @@
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.wrapper,
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #263238;
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* http://jeesite.com
|
||||
*/
|
||||
a, a:hover, a:active, a:focus, .form-unit, th[aria-selected=true] .ui-jqgrid-sortable {
|
||||
color:#1e5edb;
|
||||
}
|
||||
.main-header .navbar {
|
||||
background-color: #1951be;
|
||||
}
|
||||
.main-header .navbar .nav > li > a {
|
||||
color: #ffffff;
|
||||
}
|
||||
.main-header .navbar .nav > li > a:hover,
|
||||
.main-header .navbar .nav > li > a:active,
|
||||
.main-header .navbar .nav > li > a:focus,
|
||||
.main-header .navbar .nav .open > a,
|
||||
.main-header .navbar .nav .open > a:hover,
|
||||
.main-header .navbar .nav .open > a:focus,
|
||||
.main-header .navbar .nav > .active > a {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #f6f6f6;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle {
|
||||
color: #ffffff;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle {
|
||||
color: #fff;
|
||||
}
|
||||
.main-header .navbar .sidebar-toggle:hover {
|
||||
background-color: #367fa9;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.main-header .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.main-header .navbar .dropdown-menu li a {
|
||||
color: #fff;
|
||||
}
|
||||
.main-header .navbar .dropdown-menu li a:hover {
|
||||
background: #367fa9;
|
||||
}
|
||||
}
|
||||
.main-header .logo {
|
||||
background-color: #1951be;
|
||||
color: #ffffff;
|
||||
border-bottom: 0 solid transparent;
|
||||
}
|
||||
.main-header .logo:hover {
|
||||
background-color: #1951be;
|
||||
}
|
||||
.main-header li.user-header {
|
||||
background-color: #1951be;
|
||||
}
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.content-wrapper,
|
||||
.main-footer {
|
||||
border-left: 1px solid #eeeeee;
|
||||
}
|
||||
.user-panel > .info,
|
||||
.user-panel > .info > a {
|
||||
color: #555;
|
||||
}
|
||||
.sidebar-menu > li {
|
||||
-webkit-transition: border-left-color 0.3s ease;
|
||||
-o-transition: border-left-color 0.3s ease;
|
||||
transition: border-left-color 0.3s ease;
|
||||
}
|
||||
.sidebar-menu > li.header {
|
||||
color: #848484;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
.sidebar-menu > li > a {
|
||||
border-left: 3px solid transparent;
|
||||
font-weight: 600;
|
||||
}
|
||||
.sidebar-menu > li:hover > a,
|
||||
.sidebar-menu > li.active > a {
|
||||
color: #000;
|
||||
background: #ffffff;
|
||||
}
|
||||
.sidebar-menu > li.active {
|
||||
border-left-color: #1e5edb;
|
||||
}
|
||||
.sidebar-menu > li.active > a {
|
||||
font-weight: 600;
|
||||
}
|
||||
.sidebar-menu > li.menu-open > a,
|
||||
.sidebar-menu > li > .treeview-menu {
|
||||
background: #ffffff;
|
||||
}
|
||||
.sidebar a {
|
||||
color: #555;
|
||||
}
|
||||
.sidebar a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.treeview-menu > li > a {
|
||||
color: #555;
|
||||
}
|
||||
.treeview-menu > li.active > a,
|
||||
.treeview-menu > li > a:hover {
|
||||
color: #000;
|
||||
}
|
||||
.sidebar-form {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #d2d6de;
|
||||
margin: 10px 10px;
|
||||
}
|
||||
.sidebar-form input[type="text"],
|
||||
.sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #fff;
|
||||
border: 1px solid transparent;
|
||||
height: 35px;
|
||||
}
|
||||
.sidebar-form input[type="text"] {
|
||||
color: #666;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px;
|
||||
}
|
||||
.sidebar-form input[type="text"]:focus,
|
||||
.sidebar-form input[type="text"]:focus + .input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666;
|
||||
}
|
||||
.sidebar-form input[type="text"]:focus + .input-group-btn .btn {
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
.main-footer {
|
||||
border-top-color: #d2d6de;
|
||||
}
|
||||
.skin-blue.layout-top-nav .main-header > .logo {
|
||||
background-color: #1e5edb;
|
||||
color: #ffffff;
|
||||
border-bottom: 0 solid transparent;
|
||||
}
|
||||
.skin-blue.layout-top-nav .main-header > .logo:hover {
|
||||
background-color: #3b8ab8;
|
||||
}
|
||||
|
||||
.sidebar-menu .treeview-item.active > a {color:#001C6B;background-color:#e1f1ff;border-right:solid #7791ce;}
|
||||
|
||||
.content-wrapper, .right-side, body {background-color:#f8f8f8;}
|
||||
|
||||
.btn-primary, .btn-primary:hover, .btn-primary:active,
|
||||
.btn-primary.hover, .btn-primary.focus, .btn-primary:focus,
|
||||
.btn-primary.active.focus, .btn-primary.active:focus, .btn-primary.active:hover,
|
||||
.btn-primary:active.focus, .btn-primary:active:focus, .btn-primary:active:hover,
|
||||
.open>.dropdown-toggle.btn-primary.focus, .open>.dropdown-toggle.btn-primary:focus,
|
||||
.open>.dropdown-toggle.btn-primary:hover, .layui-layer-btn .layui-layer-btn0,
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice,
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected],
|
||||
.wup_container .placeholder .webuploader-pick {background-color:#1e5edb!important;border-color:#1e5edb!important;}
|
||||
.form-unit, th[aria-selected=true] .ui-jqgrid-sortable {color:#1e5edb;}
|
||||
.form-unit {border-bottom: 1px solid #eee;}
|
||||
|
||||
.tabpanel_mover li {padding:1px 16px 2px 3px;margin:6px 0 6px 6px;border:1px solid #e4e4e4;
|
||||
border-radius:3px;background:#fff;box-shadow:0 0 5px #e6e6e6;}
|
||||
.tabpanel_mover li.active {background-color:#1e5edb;}
|
||||
.tabpanel_mover li.active div {color:#fff;}
|
||||
.tabpanel_mover li .closer {font:11px/1 FontAwesome;top:6px;right:2px;background:none;opacity:0.7;}
|
||||
.tabpanel_mover li .closer:before {content:"\f00d";}
|
||||
.tabpanel_mover li .closer:hover {background:none;-moz-transform: scale(1.2);-webkit-transform: scale(1.2);
|
||||
-o-transform: scale(1.2);-ms-transform: scale(1.2);transform: scale(1.2);color:#d30606;}
|
||||
.tabpanel_mover li.active .closer:hover {color:#fff;opacity:0.9;}
|
||||
.tabpanel_tab_content {background-color:#fafafa;border-bottom-color:#eeeeee;overflow:visible;}
|
||||
/* .tabpanel_mover li {background:#fff;border-right:1px solid #eee;padding:8px 16px 8px 5px;}
|
||||
.tabpanel_mover li.active {background-color:#fff;border-bottom:3px solid #1e5edb;}
|
||||
.tabpanel_mover li.active div {color:#0975d9;}
|
||||
.tabpanel_mover li .closer {background:none;font:11px/1 FontAwesome;opacity:0.7;}
|
||||
.tabpanel_mover li .closer:before {content:"\f00d";}
|
||||
.tabpanel_mover li .closer:hover {background:none;-moz-transform: scale(1.2);-webkit-transform: scale(1.2);
|
||||
-o-transform: scale(1.2);-ms-transform: scale(1.2);transform: scale(1.2);color:#d30606;}
|
||||
.tabpanel_tab_content {background-color:#fafafa;border-bottom-color:#eeeeee;overflow:visible;} 替换上面 tab 样式,改变 tab 风格。*/
|
||||
|
||||
/* .main-content {padding:10px;}
|
||||
.ui-layout-container {padding:10px;}
|
||||
.ui-layout-resizer {background:transparent;}
|
||||
.ui-layout-pane {box-shadow:0 0 5px #e0e0e0;}
|
||||
.ui-layout-pane>.main-content {padding:0;}
|
||||
.ui-layout-content>.wrapper>.main-content {padding:0;}
|
||||
.box-main,.nav-main{border-radius:3px;box-shadow:0 0 5px #e0e0e0;} 解开注释,可给内容页面,添加内边距样式 */
|
||||
.box-main>.box-header {border-bottom-color:#eeeeee;}
|
||||
.box-main>.box-header .box-title .fa {color:#1e5edb;}
|
||||
.nav-tabs-custom>.nav-tabs>li.active {border-top-color:#1e5edb;}
|
||||
.form-control:focus,.select2-container--default.select2-container--focus .select2-selection--multiple,
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {border-color:#6980c3!important;}
|
||||
.table thead tr, .ui-jqgrid-htable thead tr, .ui-jqgrid-hdiv, .ui-jqgrid-hbox {background-color:#f6f6f6;}
|
||||
.ui-jqgrid .ui-jqgrid-htable th.ui-th-column-header, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column,
|
||||
.ui-jqgrid .ui-jqgrid-labels th, .ui-jqgrid .ui-widget-content, .ui-jqgrid tr.ui-row-ltr td,
|
||||
.ui-jqgrid tr.ui-row-rtl td, .ui-jqgrid tr.ui-row-ltr td:last-child {border-color:#eaeaea;}
|
||||
.ui-state-hover td, .ui-widget-content .ui-state-hover td, .ui-widget-header .ui-state-hover td,
|
||||
.ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {background:#f5f5f5;}
|
||||
.ui-jqgrid tr.ui-state-highlight.ui-row-ltr td {background-color:#e5f3ff;}
|
||||
/* .ui-jqgrid tr.ui-row-ltr td {border-right:0!important;} 解开注释,可去除表格单元格的竖边框线 */
|
||||
@@ -56,7 +56,6 @@
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.wrapper,
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #263238;
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.wrapper,
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #263238;
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.wrapper,
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #263238;
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
.content-header {
|
||||
background: transparent;
|
||||
}
|
||||
.wrapper,
|
||||
.sidebar,
|
||||
.left-side {
|
||||
background-color: #263238;
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* Default Layout Theme
|
||||
*
|
||||
* Created for jquery.layout
|
||||
*
|
||||
* Copyright (c) 2010
|
||||
* Fabrizio Balliano (http://www.fabrizioballiano.net)
|
||||
* Kevin Dalman (http://allpro.net)
|
||||
*
|
||||
* Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
|
||||
* and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
|
||||
*
|
||||
* Last Updated: 2010-02-10
|
||||
* NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
|
||||
*/
|
||||
|
||||
.ui-draggable-handle{-ms-touch-action:none;touch-action:none}
|
||||
|
||||
/*
|
||||
* DEFAULT FONT
|
||||
* Just to make demo-pages look better - not actually relevant to Layout!
|
||||
*/
|
||||
/* body { */
|
||||
/* font-family: Geneva, Arial, Helvetica, sans-serif; */
|
||||
/* font-size: 100%; */
|
||||
/* *font-size: 80%; */
|
||||
/* } */
|
||||
|
||||
/*
|
||||
* PANES & CONTENT-DIVs
|
||||
*/
|
||||
.ui-layout-pane { /* all 'panes' */
|
||||
/* background: #FFF; */
|
||||
/* border: 1px solid #eee; */
|
||||
/* padding: 10px; */
|
||||
overflow: auto;
|
||||
/* DO NOT add scrolling (or padding) to 'panes' that have a content-div,
|
||||
otherwise you may get double-scrollbars - on the pane AND on the content-div
|
||||
- use ui-layout-wrapper class if pane has a content-div
|
||||
- use ui-layout-container if pane has an inner-layout
|
||||
*/
|
||||
}
|
||||
/* (scrolling) content-div inside pane allows for fixed header(s) and/or footer(s) */
|
||||
.ui-layout-content {
|
||||
padding: 10px;
|
||||
position: relative; /* contain floated or positioned elements */
|
||||
overflow: auto; /* add scrolling to content-div */
|
||||
width: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* UTILITY CLASSES
|
||||
* Must come AFTER pane-class above so will override
|
||||
* These classes are NOT auto-generated and are NOT used by Layout
|
||||
*/
|
||||
.layout-child-container,
|
||||
.layout-content-container {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.layout-child-container {
|
||||
border: 0; /* remove border because inner-layout-panes probably have borders */
|
||||
}
|
||||
.layout-scroll {
|
||||
overflow: auto;
|
||||
}
|
||||
.layout-hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* RESIZER-BARS
|
||||
*/
|
||||
.ui-layout-resizer { /* all 'resizer-bars' */
|
||||
background: #fafafa;
|
||||
border: 1px solid #eee;
|
||||
border-width: 0;
|
||||
}
|
||||
.ui-layout-resizer-drag { /* REAL resizer while resize in progress */
|
||||
}
|
||||
.ui-layout-resizer-hover { /* affects both open and closed states */
|
||||
}
|
||||
/* NOTE: It looks best when 'hover' and 'dragging' are set to the same color,
|
||||
otherwise color shifts while dragging when bar can't keep up with mouse */
|
||||
.ui-layout-resizer-open-hover , /* hover-color to 'resize' */
|
||||
.ui-layout-resizer-dragging { /* resizer beging 'dragging' */
|
||||
background: #fafafa;
|
||||
}
|
||||
.ui-layout-resizer-dragging { /* CLONED resizer being dragged */
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
.ui-layout-resizer-north-dragging,
|
||||
.ui-layout-resizer-south-dragging {
|
||||
border-width: 1px 0;
|
||||
}
|
||||
.ui-layout-resizer-west-dragging,
|
||||
.ui-layout-resizer-east-dragging {
|
||||
border-width: 0 1px;
|
||||
}
|
||||
/* NOTE: Add a 'dragging-limit' color to provide visual feedback when resizer hits min/max size limits */
|
||||
.ui-layout-resizer-dragging-limit { /* CLONED resizer at min or max size-limit */
|
||||
background: #E1A4A4; /* red */
|
||||
}
|
||||
|
||||
.ui-layout-resizer-closed-hover { /* hover-color to 'slide open' */
|
||||
background: #EBD5AA;
|
||||
}
|
||||
.ui-layout-resizer-sliding { /* resizer when pane is 'slid open' */
|
||||
/* opacity: .10; show only a slight shadow */
|
||||
/* filter: alpha(opacity=10); */
|
||||
}
|
||||
.ui-layout-resizer-sliding-hover { /* sliding resizer - hover */
|
||||
/* opacity: 1.00; on-hover, show the resizer-bar normally */
|
||||
/* filter: alpha(opacity=100); */
|
||||
}
|
||||
/* sliding resizer - add 'outside-border' to resizer on-hover
|
||||
* this sample illustrates how to target specific panes and states */
|
||||
.ui-layout-resizer-north-sliding-hover { border-bottom-width: 1px; }
|
||||
.ui-layout-resizer-south-sliding-hover { border-top-width: 1px; }
|
||||
.ui-layout-resizer-west-sliding-hover { border-right-width: 1px; }
|
||||
.ui-layout-resizer-east-sliding-hover { border-left-width: 1px; }
|
||||
|
||||
/*
|
||||
* TOGGLER-BUTTONS
|
||||
*/
|
||||
.ui-layout-toggler {
|
||||
border: 1px solid #eee; /* match pane-border */
|
||||
background-color: #eee;
|
||||
}
|
||||
.ui-layout-resizer-hover .ui-layout-toggler {
|
||||
opacity: 1.00;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
.ui-layout-toggler-hover , /* need when NOT resizable */
|
||||
.ui-layout-resizer-hover .ui-layout-toggler-hover { /* need specificity when IS resizable */
|
||||
background-color: #FC6;
|
||||
opacity: 1.00;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
.ui-layout-toggler-north ,
|
||||
.ui-layout-toggler-south {
|
||||
border-width: 0 1px; /* left/right borders */
|
||||
}
|
||||
.ui-layout-toggler-west ,
|
||||
.ui-layout-toggler-east {
|
||||
border-width: 1px 0; /* top/bottom borders */
|
||||
}
|
||||
/* hide the toggler-button when the pane is 'slid open' */
|
||||
.ui-layout-resizer-sliding .ui-layout-toggler {
|
||||
display: none;
|
||||
}
|
||||
/*
|
||||
* style the text we put INSIDE the togglers
|
||||
*/
|
||||
.ui-layout-toggler .ui-content {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 8px;
|
||||
width: 100%;
|
||||
padding-bottom: 0.35ex; /* to 'vertically center' text inside text-span */
|
||||
}
|
||||
.ui-layout-toggler .ui-content .fa{
|
||||
line-height: 8px;
|
||||
}
|
||||
|
||||
.ui-layout-toggler-north-closed .fa:before,
|
||||
.ui-layout-toggler-south-open .fa:before {
|
||||
content: "\f0d7";/* 下 */
|
||||
}
|
||||
.ui-layout-toggler-south-closed .fa:before,
|
||||
.ui-layout-toggler-north-open .fa:before {
|
||||
content: "\f0d8";/* 上 */
|
||||
}
|
||||
.ui-layout-toggler-west-closed .fa:before,
|
||||
.ui-layout-toggler-east-open .fa:before {
|
||||
content: "\f0da";/* 右 */
|
||||
}
|
||||
.ui-layout-toggler-east-closed .fa:before,
|
||||
.ui-layout-toggler-west-open .fa:before {
|
||||
content: "\f0d9";/* 左 */
|
||||
}
|
||||
|
||||
/*
|
||||
* PANE-MASKS
|
||||
* these styles are hard-coded on mask elems, but are also
|
||||
* included here as !important to ensure will overrides any generic styles
|
||||
*/
|
||||
.ui-layout-mask {
|
||||
border: none !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
overflow: hidden !important;
|
||||
position: absolute !important;
|
||||
opacity: 0 !important;
|
||||
filter: Alpha(Opacity="0") !important;
|
||||
}
|
||||
.ui-layout-mask-inside-pane { /* masks always inside pane EXCEPT when pane is an iframe */
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
div.ui-layout-mask {} /* standard mask for iframes */
|
||||
iframe.ui-layout-mask {} /* extra mask for objects/applets */
|
||||
|
||||
/*
|
||||
* Default printing styles
|
||||
*/
|
||||
@media print {
|
||||
/*
|
||||
* Unless you want to print the layout as it appears onscreen,
|
||||
* these html/body styles are needed to allow the content to 'flow'
|
||||
*/
|
||||
html {
|
||||
height: auto !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
body.ui-layout-container {
|
||||
position: static !important;
|
||||
top: auto !important;
|
||||
bottom: auto !important;
|
||||
left: auto !important;
|
||||
right: auto !important;
|
||||
/* only IE6 has container width & height set by Layout */
|
||||
_width: auto !important;
|
||||
_height: auto !important;
|
||||
}
|
||||
.ui-layout-resizer, .ui-layout-toggler {
|
||||
display: none !important;
|
||||
}
|
||||
/*
|
||||
* Default pane print styles disables positioning, borders and backgrounds.
|
||||
* You can modify these styles however it suit your needs.
|
||||
*/
|
||||
.ui-layout-pane {
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
position: relative !important;
|
||||
top: auto !important;
|
||||
bottom: auto !important;
|
||||
left: auto !important;
|
||||
right: auto !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -183,7 +183,7 @@ html #layuicss-skinlayercss{display: none; position: absolute; width: 1989px;}
|
||||
/* ThinkGem */
|
||||
.layui-layer-title {font-weight:bold;font-size:15px;background:#fff;height:45px;line-height:45px;}
|
||||
.layui-layer-page .layui-layer-content {overflow-x:hidden;}
|
||||
.layui-layer-page .layui-layer-content .licFile{padding-top:6px;}
|
||||
.layui-layer-page .layui-layer-content .form-file{padding-top:4px;}
|
||||
.layui-layer-page .layui-layer-btn, .layui-layer-iframe .layui-layer-btn {
|
||||
padding-top:3px;padding-bottom:10px;}
|
||||
.layui-layer-btn .layui-layer-btn0{border-color:#367fa9;background-color: #367fa9;}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/main/resources=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
encoding/<project>=UTF-8
|
||||
@@ -1,8 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
@@ -1,4 +0,0 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="jeesite-module-core">
|
||||
<wb-resource deploy-path="/" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
|
||||
</wb-module>
|
||||
</project-modules>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faceted-project>
|
||||
<fixed facet="jst.utility"/>
|
||||
<fixed facet="java"/>
|
||||
<installed facet="jst.utility" version="1.0"/>
|
||||
<installed facet="java" version="1.7"/>
|
||||
</faceted-project>
|
||||
@@ -1,2 +0,0 @@
|
||||
disabled=06target
|
||||
eclipse.preferences.version=1
|
||||
@@ -1,7 +0,0 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
fullBuildGoals=process-test-resources
|
||||
resolveWorkspaceProjects=true
|
||||
resourceFilterGoals=process-resources resources\:testResources
|
||||
skipCompilerPlugin=true
|
||||
version=1
|
||||
@@ -12,6 +12,6 @@ echo.
|
||||
cd %~dp0
|
||||
|
||||
cd ..
|
||||
call mvn clean javadoc:jar
|
||||
call mvn clean package -Pjavadoc
|
||||
|
||||
pause
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,40 +1,4 @@
|
||||
|
||||
/* Drop Tables */
|
||||
|
||||
IF OBJECT_ID('[js_gen_table_column]') IS NOT NULL DROP TABLE [js_gen_table_column];
|
||||
IF OBJECT_ID('[js_gen_table]') IS NOT NULL DROP TABLE [js_gen_table];
|
||||
IF OBJECT_ID('[js_sys_company_office]') IS NOT NULL DROP TABLE [js_sys_company_office];
|
||||
IF OBJECT_ID('[js_sys_employee_post]') IS NOT NULL DROP TABLE [js_sys_employee_post];
|
||||
IF OBJECT_ID('[js_sys_user_data_scope]') IS NOT NULL DROP TABLE [js_sys_user_data_scope];
|
||||
IF OBJECT_ID('[js_sys_user_role]') IS NOT NULL DROP TABLE [js_sys_user_role];
|
||||
IF OBJECT_ID('[js_sys_user]') IS NOT NULL DROP TABLE [js_sys_user];
|
||||
IF OBJECT_ID('[js_sys_employee]') IS NOT NULL DROP TABLE [js_sys_employee];
|
||||
IF OBJECT_ID('[js_sys_company]') IS NOT NULL DROP TABLE [js_sys_company];
|
||||
IF OBJECT_ID('[js_sys_area]') IS NOT NULL DROP TABLE [js_sys_area];
|
||||
IF OBJECT_ID('[js_sys_config]') IS NOT NULL DROP TABLE [js_sys_config];
|
||||
IF OBJECT_ID('[js_sys_dict_data]') IS NOT NULL DROP TABLE [js_sys_dict_data];
|
||||
IF OBJECT_ID('[js_sys_dict_type]') IS NOT NULL DROP TABLE [js_sys_dict_type];
|
||||
IF OBJECT_ID('[js_sys_file_upload]') IS NOT NULL DROP TABLE [js_sys_file_upload];
|
||||
IF OBJECT_ID('[js_sys_file_entity]') IS NOT NULL DROP TABLE [js_sys_file_entity];
|
||||
IF OBJECT_ID('[js_sys_job_log]') IS NOT NULL DROP TABLE [js_sys_job_log];
|
||||
IF OBJECT_ID('[js_sys_job]') IS NOT NULL DROP TABLE [js_sys_job];
|
||||
IF OBJECT_ID('[js_sys_lang]') IS NOT NULL DROP TABLE [js_sys_lang];
|
||||
IF OBJECT_ID('[js_sys_log]') IS NOT NULL DROP TABLE [js_sys_log];
|
||||
IF OBJECT_ID('[js_sys_role_menu]') IS NOT NULL DROP TABLE [js_sys_role_menu];
|
||||
IF OBJECT_ID('[js_sys_menu]') IS NOT NULL DROP TABLE [js_sys_menu];
|
||||
IF OBJECT_ID('[js_sys_module]') IS NOT NULL DROP TABLE [js_sys_module];
|
||||
IF OBJECT_ID('[js_sys_msg_inner_record]') IS NOT NULL DROP TABLE [js_sys_msg_inner_record];
|
||||
IF OBJECT_ID('[js_sys_msg_inner]') IS NOT NULL DROP TABLE [js_sys_msg_inner];
|
||||
IF OBJECT_ID('[js_sys_msg_push]') IS NOT NULL DROP TABLE [js_sys_msg_push];
|
||||
IF OBJECT_ID('[js_sys_msg_pushed]') IS NOT NULL DROP TABLE [js_sys_msg_pushed];
|
||||
IF OBJECT_ID('[js_sys_msg_template]') IS NOT NULL DROP TABLE [js_sys_msg_template];
|
||||
IF OBJECT_ID('[js_sys_office]') IS NOT NULL DROP TABLE [js_sys_office];
|
||||
IF OBJECT_ID('[js_sys_post]') IS NOT NULL DROP TABLE [js_sys_post];
|
||||
IF OBJECT_ID('[js_sys_role_data_scope]') IS NOT NULL DROP TABLE [js_sys_role_data_scope];
|
||||
IF OBJECT_ID('[js_sys_role]') IS NOT NULL DROP TABLE [js_sys_role];
|
||||
|
||||
|
||||
|
||||
|
||||
/* Create Tables */
|
||||
|
||||
@@ -175,7 +139,7 @@ CREATE TABLE [js_sys_config]
|
||||
[id] varchar(64) NOT NULL,
|
||||
[config_name] nvarchar(100) NOT NULL,
|
||||
[config_key] varchar(100) NOT NULL,
|
||||
[config_value] nvarchar(1000) NOT NULL,
|
||||
[config_value] nvarchar(1000),
|
||||
[is_sys] char(1) NOT NULL,
|
||||
[create_by] varchar(64) NOT NULL,
|
||||
[create_date] datetime NOT NULL,
|
||||
@@ -292,7 +256,7 @@ CREATE TABLE [js_sys_file_entity]
|
||||
[file_path] nvarchar(1000) NOT NULL,
|
||||
[file_content_type] varchar(200) NOT NULL,
|
||||
[file_extension] varchar(100) NOT NULL,
|
||||
[file_size] decimal(38) NOT NULL,
|
||||
[file_size] decimal(31) NOT NULL,
|
||||
PRIMARY KEY ([file_id])
|
||||
);
|
||||
|
||||
@@ -788,8 +752,8 @@ CREATE TABLE [js_sys_user_role]
|
||||
|
||||
/* Create Indexes */
|
||||
|
||||
CREATE INDEX [idx_gen_table_ptn] ON [js_gen_table] ();
|
||||
CREATE INDEX [idx_gen_table_column_tn] ON [js_gen_table_column] ();
|
||||
CREATE INDEX [idx_gen_table_ptn] ON [js_gen_table] ([parent_table_name]);
|
||||
CREATE INDEX [idx_gen_table_column_tn] ON [js_gen_table_column] ([table_name]);
|
||||
CREATE INDEX [idx_sys_area_pc] ON [js_sys_area] ([parent_code]);
|
||||
CREATE INDEX [idx_sys_area_ts] ON [js_sys_area] ([tree_sort]);
|
||||
CREATE INDEX [idx_sys_area_status] ON [js_sys_area] ([status]);
|
||||
|
||||
@@ -1,41 +1,5 @@
|
||||
SET SESSION FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
/* Drop Tables */
|
||||
|
||||
DROP TABLE IF EXISTS js_gen_table_column;
|
||||
DROP TABLE IF EXISTS js_gen_table;
|
||||
DROP TABLE IF EXISTS js_sys_company_office;
|
||||
DROP TABLE IF EXISTS js_sys_employee_post;
|
||||
DROP TABLE IF EXISTS js_sys_user_data_scope;
|
||||
DROP TABLE IF EXISTS js_sys_user_role;
|
||||
DROP TABLE IF EXISTS js_sys_user;
|
||||
DROP TABLE IF EXISTS js_sys_employee;
|
||||
DROP TABLE IF EXISTS js_sys_company;
|
||||
DROP TABLE IF EXISTS js_sys_area;
|
||||
DROP TABLE IF EXISTS js_sys_config;
|
||||
DROP TABLE IF EXISTS js_sys_dict_data;
|
||||
DROP TABLE IF EXISTS js_sys_dict_type;
|
||||
DROP TABLE IF EXISTS js_sys_file_upload;
|
||||
DROP TABLE IF EXISTS js_sys_file_entity;
|
||||
DROP TABLE IF EXISTS js_sys_job_log;
|
||||
DROP TABLE IF EXISTS js_sys_job;
|
||||
DROP TABLE IF EXISTS js_sys_lang;
|
||||
DROP TABLE IF EXISTS js_sys_log;
|
||||
DROP TABLE IF EXISTS js_sys_role_menu;
|
||||
DROP TABLE IF EXISTS js_sys_menu;
|
||||
DROP TABLE IF EXISTS js_sys_module;
|
||||
DROP TABLE IF EXISTS js_sys_msg_inner_record;
|
||||
DROP TABLE IF EXISTS js_sys_msg_inner;
|
||||
DROP TABLE IF EXISTS js_sys_msg_push;
|
||||
DROP TABLE IF EXISTS js_sys_msg_pushed;
|
||||
DROP TABLE IF EXISTS js_sys_msg_template;
|
||||
DROP TABLE IF EXISTS js_sys_office;
|
||||
DROP TABLE IF EXISTS js_sys_post;
|
||||
DROP TABLE IF EXISTS js_sys_role_data_scope;
|
||||
DROP TABLE IF EXISTS js_sys_role;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Create Tables */
|
||||
|
||||
@@ -176,7 +140,7 @@ CREATE TABLE js_sys_config
|
||||
id varchar(64) NOT NULL COMMENT '编号',
|
||||
config_name varchar(100) NOT NULL COMMENT '名称',
|
||||
config_key varchar(100) NOT NULL COMMENT '参数键',
|
||||
config_value varchar(1000) NOT NULL COMMENT '参数值',
|
||||
config_value varchar(1000) COMMENT '参数值',
|
||||
is_sys char(1) NOT NULL COMMENT '系统内置(1是 0否)',
|
||||
create_by varchar(64) NOT NULL COMMENT '创建者',
|
||||
create_date datetime NOT NULL COMMENT '创建时间',
|
||||
@@ -293,7 +257,7 @@ CREATE TABLE js_sys_file_entity
|
||||
file_path varchar(1000) NOT NULL COMMENT '文件相对路径',
|
||||
file_content_type varchar(200) NOT NULL COMMENT '文件内容类型',
|
||||
file_extension varchar(100) NOT NULL COMMENT '文件后缀扩展名',
|
||||
file_size decimal(38) NOT NULL COMMENT '文件大小(单位B)',
|
||||
file_size decimal(31) NOT NULL COMMENT '文件大小(单位B)',
|
||||
PRIMARY KEY (file_id),
|
||||
UNIQUE (file_md5)
|
||||
) COMMENT = '文件实体表';
|
||||
@@ -790,8 +754,8 @@ CREATE TABLE js_sys_user_role
|
||||
|
||||
/* Create Indexes */
|
||||
|
||||
CREATE INDEX idx_gen_table_ptn ON js_gen_table ();
|
||||
CREATE INDEX idx_gen_table_column_tn ON js_gen_table_column ();
|
||||
CREATE INDEX idx_gen_table_ptn ON js_gen_table (parent_table_name ASC);
|
||||
CREATE INDEX idx_gen_table_column_tn ON js_gen_table_column (table_name ASC);
|
||||
CREATE INDEX idx_sys_area_pc ON js_sys_area (parent_code ASC);
|
||||
CREATE INDEX idx_sys_area_ts ON js_sys_area (tree_sort ASC);
|
||||
CREATE INDEX idx_sys_area_status ON js_sys_area (status ASC);
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
-- 打开 my.ini 给 [mysqld] 增加如下配置:
|
||||
-- sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
|
||||
|
||||
set global read_only=0;
|
||||
|
||||
create user 'jeesite'@'%' identified by 'jeesite';
|
||||
|
||||
create database jeesite DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
grant all privileges on jeesite.* to 'jeesite'@'%' identified by 'jeesite';
|
||||
|
||||
flush privileges;
|
||||
@@ -1,40 +1,4 @@
|
||||
|
||||
/* Drop Tables */
|
||||
|
||||
DROP TABLE js_gen_table_column CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_gen_table CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_company_office CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_employee_post CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_user_data_scope CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_user_role CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_user CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_employee CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_company CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_area CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_config CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_dict_data CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_dict_type CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_file_upload CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_file_entity CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_job_log CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_job CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_lang CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_log CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_role_menu CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_menu CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_module CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_msg_inner_record CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_msg_inner CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_msg_push CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_msg_pushed CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_msg_template CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_office CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_post CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_role_data_scope CASCADE CONSTRAINTS;
|
||||
DROP TABLE js_sys_role CASCADE CONSTRAINTS;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Create Tables */
|
||||
|
||||
@@ -175,7 +139,7 @@ CREATE TABLE js_sys_config
|
||||
id varchar2(64) NOT NULL,
|
||||
config_name nvarchar2(100) NOT NULL,
|
||||
config_key varchar2(100) NOT NULL,
|
||||
config_value nvarchar2(1000) NOT NULL,
|
||||
config_value nvarchar2(1000),
|
||||
is_sys char(1) NOT NULL,
|
||||
create_by varchar2(64) NOT NULL,
|
||||
create_date timestamp NOT NULL,
|
||||
@@ -292,7 +256,7 @@ CREATE TABLE js_sys_file_entity
|
||||
file_path nvarchar2(1000) NOT NULL,
|
||||
file_content_type varchar2(200) NOT NULL,
|
||||
file_extension varchar2(100) NOT NULL,
|
||||
file_size number(38) NOT NULL,
|
||||
file_size number(31) NOT NULL,
|
||||
PRIMARY KEY (file_id)
|
||||
);
|
||||
|
||||
@@ -788,8 +752,8 @@ CREATE TABLE js_sys_user_role
|
||||
|
||||
/* Create Indexes */
|
||||
|
||||
CREATE INDEX idx_gen_table_ptn ON js_gen_table ();
|
||||
CREATE INDEX idx_gen_table_column_tn ON js_gen_table_column ();
|
||||
CREATE INDEX idx_gen_table_ptn ON js_gen_table (parent_table_name);
|
||||
CREATE INDEX idx_gen_table_column_tn ON js_gen_table_column (table_name);
|
||||
CREATE INDEX idx_sys_area_pc ON js_sys_area (parent_code);
|
||||
CREATE INDEX idx_sys_area_ts ON js_sys_area (tree_sort);
|
||||
CREATE INDEX idx_sys_area_status ON js_sys_area (status);
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
create user jeesite
|
||||
identified by jeesite
|
||||
quota unlimited on users;
|
||||
|
||||
grant connect,resource,create session,select any table,
|
||||
create any view,create any table,create any index,
|
||||
drop any table,drop any view,drop any index
|
||||
to jeesite;
|
||||
|
||||
-- 多数据源分布式事务下,需要对目标用户进行如下授权,否则会提示错误:ResourceException: Error in recovery
|
||||
grant select on sys.dba_pending_transactions to jeesite;
|
||||
grant select on sys.pending_trans$ to jeesite;
|
||||
grant select on sys.dba_2pc_pending to jeesite;
|
||||
grant execute on sys.dbms_system to jeesite;
|
||||
@@ -1,40 +1,4 @@
|
||||
|
||||
/* Drop Tables */
|
||||
|
||||
DROP TABLE IF EXISTS js_gen_table_column;
|
||||
DROP TABLE IF EXISTS js_gen_table;
|
||||
DROP TABLE IF EXISTS js_sys_company_office;
|
||||
DROP TABLE IF EXISTS js_sys_employee_post;
|
||||
DROP TABLE IF EXISTS js_sys_user_data_scope;
|
||||
DROP TABLE IF EXISTS js_sys_user_role;
|
||||
DROP TABLE IF EXISTS js_sys_user;
|
||||
DROP TABLE IF EXISTS js_sys_employee;
|
||||
DROP TABLE IF EXISTS js_sys_company;
|
||||
DROP TABLE IF EXISTS js_sys_area;
|
||||
DROP TABLE IF EXISTS js_sys_config;
|
||||
DROP TABLE IF EXISTS js_sys_dict_data;
|
||||
DROP TABLE IF EXISTS js_sys_dict_type;
|
||||
DROP TABLE IF EXISTS js_sys_file_upload;
|
||||
DROP TABLE IF EXISTS js_sys_file_entity;
|
||||
DROP TABLE IF EXISTS js_sys_job_log;
|
||||
DROP TABLE IF EXISTS js_sys_job;
|
||||
DROP TABLE IF EXISTS js_sys_lang;
|
||||
DROP TABLE IF EXISTS js_sys_log;
|
||||
DROP TABLE IF EXISTS js_sys_role_menu;
|
||||
DROP TABLE IF EXISTS js_sys_menu;
|
||||
DROP TABLE IF EXISTS js_sys_module;
|
||||
DROP TABLE IF EXISTS js_sys_msg_inner_record;
|
||||
DROP TABLE IF EXISTS js_sys_msg_inner;
|
||||
DROP TABLE IF EXISTS js_sys_msg_push;
|
||||
DROP TABLE IF EXISTS js_sys_msg_pushed;
|
||||
DROP TABLE IF EXISTS js_sys_msg_template;
|
||||
DROP TABLE IF EXISTS js_sys_office;
|
||||
DROP TABLE IF EXISTS js_sys_post;
|
||||
DROP TABLE IF EXISTS js_sys_role_data_scope;
|
||||
DROP TABLE IF EXISTS js_sys_role;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Create Tables */
|
||||
|
||||
@@ -175,7 +139,7 @@ CREATE TABLE js_sys_config
|
||||
id varchar(64) NOT NULL,
|
||||
config_name varchar(100) NOT NULL,
|
||||
config_key varchar(100) NOT NULL,
|
||||
config_value varchar(1000) NOT NULL,
|
||||
config_value varchar(1000),
|
||||
is_sys char(1) NOT NULL,
|
||||
create_by varchar(64) NOT NULL,
|
||||
create_date timestamp NOT NULL,
|
||||
@@ -292,7 +256,7 @@ CREATE TABLE js_sys_file_entity
|
||||
file_path varchar(1000) NOT NULL,
|
||||
file_content_type varchar(200) NOT NULL,
|
||||
file_extension varchar(100) NOT NULL,
|
||||
file_size decimal(38) NOT NULL,
|
||||
file_size decimal(31) NOT NULL,
|
||||
PRIMARY KEY (file_id)
|
||||
) WITHOUT OIDS;
|
||||
|
||||
@@ -788,8 +752,8 @@ CREATE TABLE js_sys_user_role
|
||||
|
||||
/* Create Indexes */
|
||||
|
||||
CREATE INDEX idx_gen_table_ptn ON js_gen_table ();
|
||||
CREATE INDEX idx_gen_table_column_tn ON js_gen_table_column ();
|
||||
CREATE INDEX idx_gen_table_ptn ON js_gen_table (parent_table_name);
|
||||
CREATE INDEX idx_gen_table_column_tn ON js_gen_table_column (table_name);
|
||||
CREATE INDEX idx_sys_area_pc ON js_sys_area (parent_code);
|
||||
CREATE INDEX idx_sys_area_ts ON js_sys_area (tree_sort);
|
||||
CREATE INDEX idx_sys_area_status ON js_sys_area (status);
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.jeesite</groupId>
|
||||
<artifactId>jeesite-parent</artifactId>
|
||||
<version>4.0.3-SNAPSHOT</version>
|
||||
<relativePath>../../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>com.jeesite</groupId>
|
||||
<artifactId>jeesite-parent</artifactId>
|
||||
<version>4.0.8-SNAPSHOT</version>
|
||||
<relativePath>../../parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>jeesite-module-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -58,42 +58,4 @@
|
||||
<url>http://jeesite.com</url>
|
||||
</organization>
|
||||
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<id>aliyun-repos</id>
|
||||
<name>Aliyun Repository</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
|
||||
<releases><enabled>true</enabled></releases>
|
||||
<snapshots><enabled>false</enabled></snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype-repos</id>
|
||||
<name>Sonatype Repository</name>
|
||||
<url>https://oss.sonatype.org/content/groups/public</url>
|
||||
<releases><enabled>true</enabled></releases>
|
||||
<snapshots><enabled>false</enabled></snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype-repos-s</id>
|
||||
<name>Sonatype Repository</name>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<releases><enabled>false</enabled></releases>
|
||||
<snapshots><enabled>true</enabled></snapshots>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
|
||||
<pluginRepository>
|
||||
<id>aliyun-repos</id>
|
||||
<name>Aliyun Repository</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
|
||||
<releases><enabled>true</enabled></releases>
|
||||
<snapshots><enabled>false</enabled></snapshots>
|
||||
</pluginRepository>
|
||||
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
@@ -15,17 +16,18 @@ import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.shiro.realm.BaseAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.CasAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.LoginInfo;
|
||||
|
||||
/**
|
||||
* CAS过滤器
|
||||
* @author ThinkGem
|
||||
* @version 2017-03-22
|
||||
* @version 2018-7-11
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
|
||||
|
||||
private BaseAuthorizingRealm authorizingRealm; // 安全认证类
|
||||
private CasAuthorizingRealm authorizingRealm; // 安全认证类
|
||||
|
||||
/**
|
||||
* 登录成功调用事件
|
||||
@@ -34,8 +36,8 @@ public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
|
||||
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
|
||||
|
||||
// 登录成功后初始化授权信息并处理登录后的操作
|
||||
authorizingRealm.onLoginSuccess(subject.getPrincipals());
|
||||
|
||||
authorizingRealm.onLoginSuccess((LoginInfo)subject.getPrincipal(), (HttpServletRequest)request);
|
||||
|
||||
String url = request.getParameter("__url");
|
||||
if (StringUtils.isNotBlank(url)) {
|
||||
WebUtils.issueRedirect(request, response, url, null, true);
|
||||
@@ -80,7 +82,7 @@ public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
|
||||
}
|
||||
}
|
||||
|
||||
public void setAuthorizingRealm(BaseAuthorizingRealm authorizingRealm) {
|
||||
public void setAuthorizingRealm(CasAuthorizingRealm authorizingRealm) {
|
||||
this.authorizingRealm = authorizingRealm;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,18 +23,21 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jeesite.common.codec.DesUtils;
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.network.IpUtils;
|
||||
import com.jeesite.common.shiro.authc.FormToken;
|
||||
import com.jeesite.common.shiro.realm.BaseAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.LoginInfo;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
/**
|
||||
* 表单验证(包含验证码)过滤类
|
||||
* @author ThinkGem
|
||||
* @version 2017-03-22
|
||||
* @version 2018-7-11
|
||||
*/
|
||||
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {
|
||||
|
||||
@@ -92,7 +95,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
}
|
||||
// 登录成功后,判断是否需要记住用户名
|
||||
if (WebUtils.isTrue(request, DEFAULT_REMEMBER_USERCODE_PARAM)) {
|
||||
rememberUserCodeCookie.setValue(username);
|
||||
rememberUserCodeCookie.setValue(EncodeUtils.xssFilter(username));
|
||||
rememberUserCodeCookie.saveTo((HttpServletRequest)request, (HttpServletResponse)response);
|
||||
} else {
|
||||
rememberUserCodeCookie.removeFrom((HttpServletRequest)request, (HttpServletResponse)response);
|
||||
@@ -156,6 +159,9 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
return captcha;
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转登录页时,跳转到默认首页
|
||||
*/
|
||||
@Override
|
||||
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
|
||||
PermissionsAuthorizationFilter.redirectToDefaultPath(request, response);
|
||||
@@ -207,6 +213,18 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
boolean isLogin = WebUtils.isTrue(request, "__login");
|
||||
return super.isLoginSubmission(request, response) || isLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行登录方法
|
||||
*/
|
||||
@Override
|
||||
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
|
||||
// 是否在登录后生成新的Session(默认false)
|
||||
if (Global.getPropertyToBoolean("shiro.isGenerateNewSessionAfterLogin", "false")){
|
||||
UserUtils.getSubject().logout();
|
||||
}
|
||||
return super.executeLogin(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功调用事件
|
||||
@@ -215,7 +233,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
|
||||
|
||||
// 登录成功后初始化授权信息并处理登录后的操作
|
||||
authorizingRealm.onLoginSuccess(subject.getPrincipals());
|
||||
authorizingRealm.onLoginSuccess((LoginInfo)subject.getPrincipal(), (HttpServletRequest) request);
|
||||
|
||||
// 登录操作如果是Ajax操作,直接返回登录信息字符串。
|
||||
if (ServletUtils.isAjaxRequest((HttpServletRequest) request)) {
|
||||
|
||||
@@ -15,6 +15,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.shiro.realm.BaseAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.LoginInfo;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
import com.jeesite.modules.sys.utils.LogUtils;
|
||||
@@ -28,6 +30,7 @@ import com.jeesite.modules.sys.utils.UserUtils;
|
||||
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
|
||||
private BaseAuthorizingRealm authorizingRealm; // 安全认证类
|
||||
|
||||
@Override
|
||||
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
|
||||
@@ -36,9 +39,19 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||
String redirectUrl = getRedirectUrl(request, response, subject);
|
||||
//try/catch added for SHIRO-298:
|
||||
try {
|
||||
// 记录用户退出日志
|
||||
LogUtils.saveLog(UserUtils.getUser(), ServletUtils.getRequest(),
|
||||
"系统退出", Log.TYPE_LOGIN_LOGOUT);
|
||||
Object principal = subject.getPrincipal();
|
||||
if (principal != null){
|
||||
// 记录用户退出日志(@Deprecated v4.0.5支持setAuthorizingRealm,之后版本可删除此if子句)
|
||||
if (authorizingRealm == null){
|
||||
LogUtils.saveLog(UserUtils.getUser(), ServletUtils.getRequest(),
|
||||
"系统退出", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
// 退出成功之前初始化授权信息并处理登录后的操作
|
||||
else{
|
||||
authorizingRealm.onLogoutSuccess((LoginInfo)subject.getPrincipal(),
|
||||
(HttpServletRequest)request);
|
||||
}
|
||||
}
|
||||
// 退出登录
|
||||
subject.logout();
|
||||
} catch (SessionException ise) {
|
||||
@@ -71,5 +84,9 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||
}
|
||||
return super.getRedirectUrl(request, response, subject);
|
||||
}
|
||||
|
||||
public void setAuthorizingRealm(BaseAuthorizingRealm authorizingRealm) {
|
||||
this.authorizingRealm = authorizingRealm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,20 +3,11 @@
|
||||
*/
|
||||
package com.jeesite.common.shiro.realm;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.utils.SpringUtils;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.entity.EmpUser;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
import com.jeesite.modules.sys.service.EmpUserService;
|
||||
import com.jeesite.modules.sys.service.UserService;
|
||||
import com.jeesite.modules.sys.utils.LogUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
@@ -24,48 +15,35 @@ import com.jeesite.modules.sys.utils.UserUtils;
|
||||
/**
|
||||
* 系统安全认证实现类
|
||||
* @author ThinkGem
|
||||
* @version 2017-03-22
|
||||
* @version 2018-7-11
|
||||
*/
|
||||
public class AuthorizingRealm extends com.jeesite.common.shiro.realm.BaseAuthorizingRealm {
|
||||
public class AuthorizingRealm extends BaseAuthorizingRealm {
|
||||
|
||||
private UserService userService;
|
||||
private EmpUserService empUserService;
|
||||
|
||||
public AuthorizingRealm() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void casCreateEmpUser(User user, Map<String, Object> attributes) {
|
||||
EmpUser empUser = new EmpUser();
|
||||
empUser.setIsNewRecord(true);
|
||||
empUser.setMobile(user.getMobile());
|
||||
empUser.setEmail(user.getEmail());
|
||||
empUser.setPhone(user.getPhone());
|
||||
empUser.getEmployee().getCompany().setCompanyCode(EncodeUtils
|
||||
.decodeUrl(ObjectUtils.toString(attributes.get("companyCode"))));
|
||||
empUser.getEmployee().getOffice().setOfficeCode(EncodeUtils
|
||||
.decodeUrl(ObjectUtils.toString(attributes.get("officeCode"))));
|
||||
getEmpUserService().save(empUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginSuccess(PrincipalCollection principals) {
|
||||
super.onLoginSuccess(principals);
|
||||
|
||||
User user = UserUtils.getUser();
|
||||
public void onLoginSuccess(LoginInfo loginInfo, HttpServletRequest request) {
|
||||
super.onLoginSuccess(loginInfo, request);
|
||||
|
||||
// 更新登录IP、时间、会话ID等
|
||||
User user = UserUtils.get(loginInfo.getId());
|
||||
getUserService().updateUserLoginInfo(user);
|
||||
|
||||
// 记录用户登录日志
|
||||
LogUtils.saveLog(user, ServletUtils.getRequest(), "系统登录", Log.TYPE_LOGIN_LOGOUT);
|
||||
LogUtils.saveLog(user, request, "系统登录", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(User logoutUser, HttpServletRequest request) {
|
||||
public void onLogoutSuccess(LoginInfo loginInfo, HttpServletRequest request) {
|
||||
super.onLogoutSuccess(loginInfo, request);
|
||||
|
||||
// 记录用户退出日志
|
||||
LogUtils.saveLog(logoutUser, request, "系统退出", Log.TYPE_LOGIN_LOGOUT);
|
||||
User user = UserUtils.get(loginInfo.getId());
|
||||
LogUtils.saveLog(user, request, "系统退出", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
|
||||
public UserService getUserService() {
|
||||
@@ -74,12 +52,5 @@ public class AuthorizingRealm extends com.jeesite.common.shiro.realm.BaseAuthori
|
||||
}
|
||||
return userService;
|
||||
}
|
||||
|
||||
public EmpUserService getEmpUserService() {
|
||||
if (empUserService == null){
|
||||
empUserService = SpringUtils.getBean(EmpUserService.class);
|
||||
}
|
||||
return empUserService;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.common.shiro.realm;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.ValidationException;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.cas.CasToken;
|
||||
import org.jasig.cas.client.authentication.AttributePrincipal;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
|
||||
import org.jasig.cas.client.validation.TicketValidationException;
|
||||
import org.jasig.cas.client.validation.TicketValidator;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
||||
import com.beust.jcommander.internal.Maps;
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.shiro.authc.FormToken;
|
||||
import com.jeesite.common.shiro.cas.CasCreateUser;
|
||||
import com.jeesite.common.shiro.cas.CasOutHandler;
|
||||
import com.jeesite.common.utils.SpringUtils;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.entity.EmpUser;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
import com.jeesite.modules.sys.service.EmpUserService;
|
||||
import com.jeesite.modules.sys.service.UserService;
|
||||
import com.jeesite.modules.sys.utils.LogUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
/**
|
||||
* 系统安全认证实现类
|
||||
* @author ThinkGem
|
||||
* @version 2018-7-11
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CasAuthorizingRealm extends BaseAuthorizingRealm {
|
||||
|
||||
private UserService userService;
|
||||
private EmpUserService empUserService;
|
||||
|
||||
private CasOutHandler casOutHandler;
|
||||
private String casServerUrl; // CAS 服务器地址
|
||||
private String casServerCallbackUrl; // CAS 服务器回调地址
|
||||
private TicketValidator ticketValidator;// CAS 令牌验证类
|
||||
|
||||
public CasAuthorizingRealm() {
|
||||
super();
|
||||
this.setAuthenticationTokenClass(CasToken.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FormToken getFormToken(AuthenticationToken authcToken) {
|
||||
|
||||
// 单点登录登出句柄(登出时注销session)有CAS中央服务器调用
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
if (casOutHandler.isLogoutRequest(request)) {
|
||||
LoginInfo loginInfo = casOutHandler.destroySession(request);
|
||||
if (loginInfo != null){
|
||||
this.onLogoutSuccess(loginInfo, request);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (authcToken == null){
|
||||
return null;
|
||||
}
|
||||
|
||||
CasToken casToken = (CasToken) authcToken;
|
||||
String ticket = (String) casToken.getCredentials();
|
||||
if (ticketValidator == null) {
|
||||
ticketValidator = new Cas20ServiceTicketValidator(casServerUrl);
|
||||
((Cas20ServiceTicketValidator)ticketValidator).setEncoding("UTF-8");
|
||||
}
|
||||
|
||||
// 进行登录身份验证
|
||||
Assertion casAssertion = null;
|
||||
try {
|
||||
casAssertion = ticketValidator.validate(ticket, casServerCallbackUrl);
|
||||
} catch (TicketValidationException e) {
|
||||
// 令牌失效,在LogoutFilter会自动跳转到登录页
|
||||
return null;
|
||||
}
|
||||
AttributePrincipal casPrincipal = casAssertion.getPrincipal();
|
||||
casToken.setUserId(casPrincipal.getName());
|
||||
|
||||
// 生成登录信息对象
|
||||
FormToken token = new FormToken();
|
||||
token.setUsername(casPrincipal.getName());
|
||||
Map<String, Object> params = Maps.newHashMap();
|
||||
params.putAll(casPrincipal.getAttributes());
|
||||
params.put("ticket", ticket);
|
||||
token.setParams(params);
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected User getUserInfo(FormToken token) {
|
||||
|
||||
User user = super.getUserInfo(token);
|
||||
if (user == null){
|
||||
Map<String, Object> attrs = token.getParams();
|
||||
|
||||
// 如果允许客户端创建账号,则创建账号
|
||||
if (ObjectUtils.toBoolean(attrs.get("isAllowClientCreateUser"))){
|
||||
|
||||
// 获取CAS传递过来的用户属性信息
|
||||
user = new User(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("userCode"))));
|
||||
user.setLoginCode(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("loginCode"))));
|
||||
user.setPassword(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("password"))));
|
||||
user.setUserName(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("userName"))));
|
||||
user.setEmail(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("email"))));
|
||||
user.setMobile(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("mobile"))));
|
||||
user.setPhone(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("phone"))));
|
||||
user.setUserType(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("userType"))));
|
||||
user.setRefCode(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("refCode"))));
|
||||
user.setRefName(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("refName"))));
|
||||
user.setMgrType(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("mgrType"))));
|
||||
user.setStatus(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("status"))));
|
||||
|
||||
// 如果是员工类型,则平台自动创建
|
||||
if (User.USER_TYPE_EMPLOYEE.equals(user.getUserType())){
|
||||
|
||||
// 保存员工和用户
|
||||
try{
|
||||
EmpUser empUser = new EmpUser();
|
||||
empUser.setIsNewRecord(true);
|
||||
empUser.setMobile(user.getMobile());
|
||||
empUser.setEmail(user.getEmail());
|
||||
empUser.setPhone(user.getPhone());
|
||||
empUser.getEmployee().getCompany().setCompanyCode(EncodeUtils
|
||||
.decodeUrl(ObjectUtils.toString(attrs.get("companyCode"))));
|
||||
empUser.getEmployee().getOffice().setOfficeCode(EncodeUtils
|
||||
.decodeUrl(ObjectUtils.toString(attrs.get("officeCode"))));
|
||||
getEmpUserService().save(empUser);
|
||||
}catch(ValidationException ve){
|
||||
throw new AuthenticationException("msg:" + ve.getMessage());
|
||||
}
|
||||
|
||||
// 重新获取用户登录
|
||||
user = UserUtils.getByLoginCode(token.getUsername()/*, corpCode*/);
|
||||
if (user != null) {
|
||||
return user;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 其它类型,根据项目需要自行创建
|
||||
else{
|
||||
try{
|
||||
CasCreateUser casCreateUser = SpringUtils.getBean(CasCreateUser.class);
|
||||
if(casCreateUser != null){
|
||||
casCreateUser.createUser(user, attrs);
|
||||
}
|
||||
}catch(NoSuchBeanDefinitionException e){
|
||||
throw new AuthenticationException("msg:用户 “" + token.getUsername()
|
||||
+ "”, 类型 “" + user.getUserType() + "” 在本系统中不存在, 请联系管理员.");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
throw new AuthenticationException("msg:用户 “" + token.getUsername() + "” 在本系统中不存在, 请联系管理员.");
|
||||
}
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertCredentialsMatch(AuthenticationToken authcToken,
|
||||
AuthenticationInfo info) throws AuthenticationException {
|
||||
// CAS的Ticket已经在doGetAuthenticationInfo()认证过了,这里就不验证身份了
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginSuccess(LoginInfo loginInfo, HttpServletRequest request) {
|
||||
super.onLoginSuccess(loginInfo, request);
|
||||
|
||||
// 单点登录登出句柄(登录时注入session),在这之前必须获取下授权信息
|
||||
String ticket = loginInfo.getParam("ticket");
|
||||
casOutHandler.recordSession(request, ticket);
|
||||
//System.out.print("__sid: "+request.getSession().getId());
|
||||
//System.out.println(" == "+UserUtils.getSession().getId());
|
||||
|
||||
// 更新登录IP、时间、会话ID等
|
||||
User user = UserUtils.get(loginInfo.getId());
|
||||
getUserService().updateUserLoginInfo(user);
|
||||
|
||||
// 记录用户登录日志
|
||||
LogUtils.saveLog(user, ServletUtils.getRequest(), "系统登录", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(LoginInfo loginInfo, HttpServletRequest request) {
|
||||
super.onLogoutSuccess(loginInfo, request);
|
||||
|
||||
// 记录用户退出日志
|
||||
User user = UserUtils.get(loginInfo.getId());
|
||||
LogUtils.saveLog(user, request, "系统退出", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
|
||||
public UserService getUserService() {
|
||||
if (userService == null){
|
||||
userService = SpringUtils.getBean(UserService.class);
|
||||
}
|
||||
return userService;
|
||||
}
|
||||
|
||||
public EmpUserService getEmpUserService() {
|
||||
if (empUserService == null){
|
||||
empUserService = SpringUtils.getBean(EmpUserService.class);
|
||||
}
|
||||
return empUserService;
|
||||
}
|
||||
|
||||
public void setCasOutHandler(CasOutHandler casOutHandler) {
|
||||
this.casOutHandler = casOutHandler;
|
||||
}
|
||||
|
||||
public void setCasServerUrl(String casServerUrl) {
|
||||
this.casServerUrl = casServerUrl;
|
||||
}
|
||||
|
||||
public void setCasServerCallbackUrl(String casServerCallbackUrl) {
|
||||
this.casServerCallbackUrl = casServerCallbackUrl;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,10 @@
|
||||
*/
|
||||
package com.jeesite.common.utils.excel.fieldtype;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.modules.sys.entity.Area;
|
||||
import com.jeesite.modules.sys.utils.AreaUtils;
|
||||
@@ -10,16 +14,23 @@ import com.jeesite.modules.sys.utils.AreaUtils;
|
||||
/**
|
||||
* 字段类型转换
|
||||
* @author ThinkGem
|
||||
* @version 2013-03-10
|
||||
* @version 2018-08-11
|
||||
* @example fieldType = AreaType.class
|
||||
*/
|
||||
public class AreaType {
|
||||
|
||||
private static ThreadLocal<List<Area>> cache = new NamedThreadLocal<>("AreaType");
|
||||
|
||||
/**
|
||||
* 获取对象值(导入)
|
||||
*/
|
||||
public static Object getValue(String val) {
|
||||
for (Area e : AreaUtils.getAreaAllList()){
|
||||
List<Area> cacheList = cache.get();
|
||||
if (cacheList == null){
|
||||
cacheList = AreaUtils.getAreaAllList();
|
||||
cache.set(cacheList);
|
||||
}
|
||||
for (Area e : cacheList){
|
||||
if (StringUtils.trimToEmpty(val).equals(e.getAreaName())){
|
||||
return e;
|
||||
}
|
||||
@@ -36,4 +47,12 @@ public class AreaType {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
public static void clearCache(){
|
||||
cache.remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
*/
|
||||
package com.jeesite.common.utils.excel.fieldtype;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.modules.sys.entity.Company;
|
||||
import com.jeesite.modules.sys.utils.EmpUtils;
|
||||
@@ -10,16 +14,23 @@ import com.jeesite.modules.sys.utils.EmpUtils;
|
||||
/**
|
||||
* 字段类型转换
|
||||
* @author ThinkGem
|
||||
* @version 2015-03-24
|
||||
* @version 2018-08-11
|
||||
* @example fieldType = CompanyType.class
|
||||
*/
|
||||
public class CompanyType {
|
||||
|
||||
private static ThreadLocal<List<Company>> cache = new NamedThreadLocal<>("CompanyType");
|
||||
|
||||
/**
|
||||
* 获取对象值(导入)
|
||||
*/
|
||||
public static Object getValue(String val) {
|
||||
for (Company e : EmpUtils.getCompanyAllList()){
|
||||
List<Company> cacheList = cache.get();
|
||||
if (cacheList == null){
|
||||
cacheList = EmpUtils.getCompanyAllList();
|
||||
cache.set(cacheList);
|
||||
}
|
||||
for (Company e : cacheList){
|
||||
if (StringUtils.trimToEmpty(val).equals(e.getCompanyName())){
|
||||
return e;
|
||||
}
|
||||
@@ -36,4 +47,11 @@ public class CompanyType {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
public static void clearCache(){
|
||||
cache.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
*/
|
||||
package com.jeesite.common.utils.excel.fieldtype;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.modules.sys.entity.Office;
|
||||
import com.jeesite.modules.sys.utils.EmpUtils;
|
||||
@@ -10,16 +14,23 @@ import com.jeesite.modules.sys.utils.EmpUtils;
|
||||
/**
|
||||
* 字段类型转换
|
||||
* @author ThinkGem
|
||||
* @version 2013-03-10
|
||||
* @version 2018-08-11
|
||||
* @example fieldType = OfficeType.class
|
||||
*/
|
||||
public class OfficeType {
|
||||
|
||||
private static ThreadLocal<List<Office>> cache = new NamedThreadLocal<>("OfficeType");
|
||||
|
||||
/**
|
||||
* 获取对象值(导入)
|
||||
*/
|
||||
public static Object getValue(String val) {
|
||||
for (Office e : EmpUtils.getOfficeAllList()){
|
||||
List<Office> cacheList = cache.get();
|
||||
if (cacheList == null){
|
||||
cacheList = EmpUtils.getOfficeAllList();
|
||||
cache.set(cacheList);
|
||||
}
|
||||
for (Office e : cacheList){
|
||||
if (StringUtils.trimToEmpty(val).equals(e.getOfficeName())){
|
||||
return e;
|
||||
}
|
||||
@@ -36,4 +47,11 @@ public class OfficeType {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
public static void clearCache(){
|
||||
cache.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ package com.jeesite.common.utils.excel.fieldtype;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.utils.SpringUtils;
|
||||
@@ -14,26 +16,26 @@ import com.jeesite.modules.sys.service.PostService;
|
||||
/**
|
||||
* 字段类型转换
|
||||
* @author ThinkGem
|
||||
* @version 2015-03-24
|
||||
* @version 2018-08-11
|
||||
* @example fieldType = PostListType.class
|
||||
*/
|
||||
public class PostListType {
|
||||
|
||||
private static PostService postService = SpringUtils.getBean(PostService.class);
|
||||
private static ThreadLocal<List<Post>> cache = new ThreadLocal<>();
|
||||
private static ThreadLocal<List<Post>> cache = new NamedThreadLocal<>("PostListType");
|
||||
|
||||
/**
|
||||
* 获取对象值(导入)
|
||||
*/
|
||||
public static Object getValue(String val) {
|
||||
List<Post> postList = ListUtils.newArrayList();
|
||||
List<Post> allPostList = cache.get();
|
||||
if (allPostList == null){
|
||||
allPostList = postService.findList(new Post());
|
||||
cache.set(allPostList); // 不知道会不会引起内存泄露,先这样用着
|
||||
List<Post> cacheList = cache.get();
|
||||
if (cacheList == null){
|
||||
cacheList = postService.findList(new Post());
|
||||
cache.set(cacheList);
|
||||
}
|
||||
for (String s : StringUtils.split(val, ",")) {
|
||||
for (Post e : allPostList) {
|
||||
for (Post e : cacheList) {
|
||||
if (StringUtils.trimToEmpty(s).equals(e.getPostName())) {
|
||||
postList.add(e);
|
||||
}
|
||||
@@ -53,4 +55,11 @@ public class PostListType {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
public static void clearCache(){
|
||||
cache.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,25 @@
|
||||
*/
|
||||
package com.jeesite.modules.config;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
import org.apache.shiro.cas.CasSubjectFactory;
|
||||
import org.apache.shiro.realm.Realm;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.shiro.cas.CasOutHandler;
|
||||
import com.jeesite.common.shiro.config.FilterChainDefinitionMap;
|
||||
@@ -26,6 +32,7 @@ import com.jeesite.common.shiro.filter.PermissionsAuthorizationFilter;
|
||||
import com.jeesite.common.shiro.filter.RolesAuthorizationFilter;
|
||||
import com.jeesite.common.shiro.filter.UserFilter;
|
||||
import com.jeesite.common.shiro.realm.AuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.CasAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.session.SessionDAO;
|
||||
import com.jeesite.common.shiro.session.SessionManager;
|
||||
import com.jeesite.common.shiro.web.ShiroFilterFactoryBean;
|
||||
@@ -34,40 +41,32 @@ import com.jeesite.common.shiro.web.WebSecurityManager;
|
||||
/**
|
||||
* Shiro配置
|
||||
* @author ThinkGem
|
||||
* @version 2017年11月30日
|
||||
* @version 2018-7-11
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Configuration
|
||||
public class ShiroConfig {
|
||||
|
||||
/**
|
||||
* 单点登录信息句柄,单点退出用
|
||||
* Apache Shiro Filter
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
public CasOutHandler casOutHandler() {
|
||||
return new CasOutHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统安全认证实现类
|
||||
*/
|
||||
@Bean
|
||||
public AuthorizingRealm authorizingRealm(SessionDAO sessionDAO, CasOutHandler casOutHandler) {
|
||||
AuthorizingRealm bean = new AuthorizingRealm();
|
||||
bean.setCachingEnabled(false);
|
||||
bean.setSessionDAO(sessionDAO);
|
||||
bean.setCasOutHandler(casOutHandler);
|
||||
bean.setCasServerUrl(Global.getProperty("shiro.casServerUrl"));
|
||||
bean.setCasServerCallbackUrl(Global.getProperty("shiro.casClientUrl") + Global.getAdminPath() + "/login-cas");
|
||||
@Order(3000)
|
||||
@ConditionalOnMissingBean(name="shiroFilterProxy")
|
||||
public FilterRegistrationBean shiroFilterProxy(ShiroFilterFactoryBean shiroFilter) throws Exception {
|
||||
FilterRegistrationBean bean = new FilterRegistrationBean();
|
||||
bean.setFilter((Filter) shiroFilter.getInstance());
|
||||
bean.addUrlPatterns("/*");
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CAS登录过滤器
|
||||
*/
|
||||
private CasAuthenticationFilter shiroCasFilter(AuthorizingRealm authorizingRealm) {
|
||||
private CasAuthenticationFilter shiroCasFilter(CasAuthorizingRealm casAuthorizingRealm) {
|
||||
CasAuthenticationFilter bean = new CasAuthenticationFilter();
|
||||
bean.setAuthorizingRealm(authorizingRealm);
|
||||
bean.setAuthorizingRealm(casAuthorizingRealm);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -83,8 +82,10 @@ public class ShiroConfig {
|
||||
/**
|
||||
* 登出过滤器
|
||||
*/
|
||||
private LogoutFilter shiroLogoutFilter() {
|
||||
return new LogoutFilter();
|
||||
private LogoutFilter shiroLogoutFilter(AuthorizingRealm authorizingRealm) {
|
||||
LogoutFilter bean = new LogoutFilter();
|
||||
bean.setAuthorizingRealm(authorizingRealm);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,15 +114,15 @@ public class ShiroConfig {
|
||||
*/
|
||||
@Bean
|
||||
public ShiroFilterFactoryBean shiroFilter(WebSecurityManager securityManager,
|
||||
AuthorizingRealm authorizingRealm) {
|
||||
AuthorizingRealm authorizingRealm, CasAuthorizingRealm casAuthorizingRealm) {
|
||||
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
|
||||
bean.setSecurityManager(securityManager);
|
||||
bean.setLoginUrl(Global.getProperty("shiro.loginUrl"));
|
||||
bean.setSuccessUrl(Global.getProperty("shiro.successUrl"));
|
||||
bean.setSuccessUrl(Global.getProperty("adminPath")+"/index");
|
||||
Map<String, Filter> filters = bean.getFilters();
|
||||
filters.put("cas", shiroCasFilter(authorizingRealm));
|
||||
filters.put("cas", shiroCasFilter(casAuthorizingRealm));
|
||||
filters.put("authc", shiroAuthcFilter(authorizingRealm));
|
||||
filters.put("logout", shiroLogoutFilter());
|
||||
filters.put("logout", shiroLogoutFilter(authorizingRealm));
|
||||
filters.put("perms", shiroPermsFilter());
|
||||
filters.put("roles", shiroRolesFilter());
|
||||
filters.put("user", shiroUserFilter());
|
||||
@@ -131,21 +132,57 @@ public class ShiroConfig {
|
||||
bean.setFilterChainDefinitionMap(chains.getObject());
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统安全认证实现类
|
||||
*/
|
||||
@Bean
|
||||
public AuthorizingRealm authorizingRealm(SessionDAO sessionDAO) {
|
||||
AuthorizingRealm bean = new AuthorizingRealm();
|
||||
bean.setSessionDAO(sessionDAO);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 单点登录信息句柄,单点退出用
|
||||
*/
|
||||
@Bean
|
||||
public CasOutHandler casOutHandler() {
|
||||
return new CasOutHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统安全认证实现类
|
||||
*/
|
||||
@Bean
|
||||
public CasAuthorizingRealm casAuthorizingRealm(SessionDAO sessionDAO, CasOutHandler casOutHandler) {
|
||||
CasAuthorizingRealm bean = new CasAuthorizingRealm();
|
||||
bean.setSessionDAO(sessionDAO);
|
||||
bean.setCasOutHandler(casOutHandler);
|
||||
bean.setCasServerUrl(Global.getProperty("shiro.casServerUrl"));
|
||||
bean.setCasServerCallbackUrl(Global.getProperty("shiro.casClientUrl") + Global.getAdminPath() + "/login-cas");
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义Shiro安全管理配置
|
||||
*/
|
||||
@Bean
|
||||
public WebSecurityManager securityManager(AuthorizingRealm authorizingRealm, SessionManager sessionManager, CacheManager shiroCacheManager) {
|
||||
public WebSecurityManager securityManager(AuthorizingRealm authorizingRealm,
|
||||
CasAuthorizingRealm casAuthorizingRealm, SessionManager sessionManager,
|
||||
CacheManager shiroCacheManager) {
|
||||
WebSecurityManager bean = new WebSecurityManager();
|
||||
bean.setRealm(authorizingRealm);
|
||||
Collection<Realm> realms = ListUtils.newArrayList();
|
||||
realms.add(authorizingRealm); // 第一个为权限授权控制类
|
||||
realms.add(casAuthorizingRealm);
|
||||
bean.setRealms(realms);
|
||||
bean.setSessionManager(sessionManager);
|
||||
bean.setCacheManager(shiroCacheManager);
|
||||
// 设置支持CAS的subjectFactory
|
||||
bean.setSubjectFactory(new CasSubjectFactory());
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shiro 生命周期处理器,实现初始化和销毁回调
|
||||
*/
|
||||
|
||||
@@ -3,19 +3,16 @@
|
||||
*/
|
||||
package com.jeesite.modules.config.web;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.web.filter.CharacterEncodingFilter;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.shiro.web.ShiroFilterFactoryBean;
|
||||
import com.jeesite.common.web.PageCachingFilter;
|
||||
|
||||
/**
|
||||
@@ -24,28 +21,15 @@ import com.jeesite.common.web.PageCachingFilter;
|
||||
* @version 2017年11月30日
|
||||
*/
|
||||
@Configuration
|
||||
public class FilterConfig {
|
||||
|
||||
/**
|
||||
* Encoding Filter
|
||||
*/
|
||||
@Bean
|
||||
@Order(1000)
|
||||
public FilterRegistrationBean characterEncodingFilter() {
|
||||
FilterRegistrationBean bean = new FilterRegistrationBean();
|
||||
bean.setFilter(new CharacterEncodingFilter());
|
||||
bean.addInitParameter("encoding", "UTF-8");
|
||||
bean.addInitParameter("forceEncoding", "true");
|
||||
bean.addUrlPatterns("/*");
|
||||
return bean;
|
||||
}
|
||||
|
||||
public class PageCacheConfig {
|
||||
|
||||
/**
|
||||
* PageCache Filter, cache .html suffix.
|
||||
*/
|
||||
@Bean
|
||||
@Order(2000)
|
||||
@ConditionalOnProperty(name = "ehcache.pageCaching.enabled", havingValue = "true")
|
||||
@ConditionalOnMissingBean(name="pageCachingFilter")
|
||||
public FilterRegistrationBean pageCachingFilter(EhCacheManagerFactoryBean ehCacheManager) {
|
||||
FilterRegistrationBean bean = new FilterRegistrationBean();
|
||||
PageCachingFilter pageCachingFilter = new PageCachingFilter();
|
||||
@@ -56,18 +40,5 @@ public class FilterConfig {
|
||||
"ehcache.pageCaching.urlPatterns"), ","));
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apache Shiro Filter
|
||||
* @throws Exception
|
||||
*/
|
||||
@Bean
|
||||
@Order(3000)
|
||||
public FilterRegistrationBean shiroFilterProxy(ShiroFilterFactoryBean shiroFilter) throws Exception {
|
||||
FilterRegistrationBean bean = new FilterRegistrationBean();
|
||||
bean.setFilter((Filter) shiroFilter.getInstance());
|
||||
bean.addUrlPatterns("/*");
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.state.web;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* EhCache管理
|
||||
* @author ThinkGem
|
||||
* @version 2017年12月31日
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value="${adminPath}/state/ehcache")
|
||||
public class EhCacheController {
|
||||
|
||||
@RequiresPermissions("sys:stste:ehcache")
|
||||
@RequestMapping(value="")
|
||||
public String index(Model model){
|
||||
model.addAttribute("message", "正在研发中,敬请期待!");
|
||||
return "modules/state/ehcacheIndex";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.state.web;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* 服务器状态
|
||||
* @author ThinkGem
|
||||
* @version 2017年12月31日
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value="${adminPath}/state/server")
|
||||
public class ServerStateController {
|
||||
|
||||
@RequiresPermissions("sys:state:server")
|
||||
@RequestMapping(value="")
|
||||
public String index(Model model){
|
||||
model.addAttribute("message", "正在研发中,敬请期待!");
|
||||
return "modules/state/serverIndex";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -257,7 +257,6 @@ public class InitCoreData extends BaseInitDataTests {
|
||||
if("save".equals(action)){
|
||||
User entity = (User)params[1];
|
||||
entity.setIsNewRecord(true);
|
||||
entity.setPassword(UserService.encryptPassword(entity.getPassword()));
|
||||
userService.save(entity);
|
||||
return null;
|
||||
}
|
||||
@@ -360,7 +359,6 @@ public class InitCoreData extends BaseInitDataTests {
|
||||
else if("save".equals(action)){
|
||||
EmpUser entity = (EmpUser)params[1];
|
||||
entity.setIsNewRecord(true);
|
||||
entity.setPassword(UserService.encryptPassword(entity.getPassword()));
|
||||
empUserService.save(entity);
|
||||
// 设置当前为管理员,否则无法保存用户角色关系
|
||||
entity.setCurrentUser(new User(User.SUPER_ADMIN_CODE));
|
||||
|
||||
Binary file not shown.
@@ -13,7 +13,8 @@ import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelField.Align;
|
||||
import com.jeesite.common.utils.excel.annotation.ExcelFields;
|
||||
import com.jeesite.common.utils.excel.fieldtype.RoleListType;
|
||||
import com.jeesite.common.utils.excel.fieldtype.CompanyType;
|
||||
import com.jeesite.common.utils.excel.fieldtype.OfficeType;
|
||||
|
||||
/**
|
||||
* 员工用户管理Entity
|
||||
@@ -25,7 +26,9 @@ import com.jeesite.common.utils.excel.fieldtype.RoleListType;
|
||||
}, joinTable={
|
||||
@JoinTable(type=Type.JOIN, entity=Employee.class, alias="e",
|
||||
on="e.emp_code=a.ref_code AND a.user_type=#{USER_TYPE_EMPLOYEE}",
|
||||
attrName="employee", columns={@Column(includeEntity=Employee.class)}),
|
||||
attrName="employee", columns={
|
||||
@Column(includeEntity=Employee.class)
|
||||
}),
|
||||
@JoinTable(type=Type.LEFT_JOIN, entity=Office.class, alias="o",
|
||||
on="o.office_code=e.office_code", attrName="employee.office",
|
||||
columns={
|
||||
@@ -74,17 +77,17 @@ public class EmpUser extends User {
|
||||
|
||||
@Valid
|
||||
@ExcelFields({
|
||||
@ExcelField(title="归属机构", attrName="office.officeName", align=Align.CENTER, sort=10),
|
||||
@ExcelField(title="归属公司", attrName="company.officeName", align = Align.CENTER, sort=20),
|
||||
@ExcelField(title="归属机构", attrName="employee.office", align=Align.CENTER, sort=10, fieldType=OfficeType.class),
|
||||
@ExcelField(title="归属公司", attrName="employee.company", align = Align.CENTER, sort=20, fieldType=CompanyType.class),
|
||||
@ExcelField(title="登录账号", attrName="loginCode", align=Align.CENTER, sort=30),
|
||||
@ExcelField(title="用户昵称", attrName="userName", align=Align.LEFT, sort=40),
|
||||
@ExcelField(title="用户昵称", attrName="userName", align=Align.CENTER, sort=40),
|
||||
@ExcelField(title="电子邮箱", attrName="email", align=Align.LEFT, sort=50),
|
||||
@ExcelField(title="手机号码", attrName="mobile", align=Align.CENTER, sort=60),
|
||||
@ExcelField(title="办公电话", attrName="phone", align=Align.CENTER, sort=70),
|
||||
@ExcelField(title="员工编码", attrName="employee.empCode", align=Align.CENTER, sort=80),
|
||||
@ExcelField(title="员工姓名", attrName="employee.empName", align=Align.CENTER, sort=95),
|
||||
@ExcelField(title="拥有角色", attrName="userRoleString", align=Align.LEFT, sort=800, fieldType=RoleListType.class),
|
||||
@ExcelField(title="最后登录日期", attrName="lastLoginDate", type=ExcelField.Type.EXPORT, dataFormat="yyyy-MM-dd HH:mm", align=Align.CENTER, sort=900),
|
||||
@ExcelField(title="拥有角色编号", attrName="userRoleString", align=Align.LEFT, sort=800, type=ExcelField.Type.IMPORT),
|
||||
@ExcelField(title="最后登录日期", attrName="lastLoginDate", align=Align.CENTER, sort=900, type=ExcelField.Type.EXPORT, dataFormat="yyyy-MM-dd HH:mm"),
|
||||
})
|
||||
public Employee getEmployee(){
|
||||
Employee employee = (Employee)super.getRefObj();
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.jeesite.common.lang.ByteUtils;
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.lang.TimeUtils;
|
||||
import com.jeesite.common.service.BaseService;
|
||||
@@ -21,12 +22,12 @@ import com.jeesite.modules.sys.utils.UserUtils;
|
||||
/**
|
||||
* 日志拦截器
|
||||
* @author ThinkGem
|
||||
* @version 2014-8-19
|
||||
* @version 2018-08-11
|
||||
*/
|
||||
public class LogInterceptor extends BaseService implements HandlerInterceptor {
|
||||
|
||||
private static final ThreadLocal<Long> startTimeThreadLocal =
|
||||
new NamedThreadLocal<Long>("ThreadLocal StartTime");
|
||||
new NamedThreadLocal<Long>("LogInterceptor StartTime");
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||
@@ -61,10 +62,10 @@ public class LogInterceptor extends BaseService implements HandlerInterceptor {
|
||||
|
||||
// 打印JVM信息。
|
||||
if (logger.isDebugEnabled()){
|
||||
logger.debug("计时结束: {} 用时: {} URI: {} 最大内存: {}m 已分配内存: {}m 已分配内存中的剩余空间: {}m 最大可用内存: {}m",
|
||||
DateUtils.formatDate(endTime, "hh:mm:ss.SSS"), TimeUtils.formatDateAgo(executeTime),
|
||||
request.getRequestURI(), Runtime.getRuntime().maxMemory()/1024/1024, Runtime.getRuntime().totalMemory()/1024/1024, Runtime.getRuntime().freeMemory()/1024/1024,
|
||||
(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024);
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
logger.debug("计时结束: {} 用时: {} URI: {} 总内存: {} 已用内存: {}",
|
||||
DateUtils.formatDate(endTime, "hh:mm:ss.SSS"), TimeUtils.formatDateAgo(executeTime), request.getRequestURI(),
|
||||
ByteUtils.formatByteSize(runtime.totalMemory()), ByteUtils.formatByteSize(runtime.totalMemory()-runtime.freeMemory()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,18 +3,28 @@
|
||||
*/
|
||||
package com.jeesite.modules.sys.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.idgen.IdGen;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.service.CrudService;
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.common.utils.excel.ExcelImport;
|
||||
import com.jeesite.common.validator.ValidatorUtils;
|
||||
import com.jeesite.modules.sys.dao.EmpUserDao;
|
||||
import com.jeesite.modules.sys.entity.EmpUser;
|
||||
import com.jeesite.modules.sys.entity.Employee;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
import com.jeesite.modules.sys.utils.EmpUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
/**
|
||||
* 员工管理Service
|
||||
@@ -93,6 +103,68 @@ public class EmpUserService extends CrudService<EmpUserDao, EmpUser> {
|
||||
employeeService.save(employee);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入用户数据
|
||||
* @param file 导入的用户数据文件
|
||||
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
|
||||
*/
|
||||
@Transactional(readOnly=false)
|
||||
public String importData(MultipartFile file, Boolean isUpdateSupport) {
|
||||
if (file == null){
|
||||
throw new ServiceException("请选择导入的数据文件!");
|
||||
}
|
||||
int successNum = 0; int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
try(ExcelImport ei = new ExcelImport(file, 2, 0)){
|
||||
List<EmpUser> list = ei.getDataList(EmpUser.class);
|
||||
for (EmpUser user : list) {
|
||||
try{
|
||||
// 验证数据文件
|
||||
ValidatorUtils.validateWithException(user);
|
||||
// 验证是否存在这个用户
|
||||
User u = UserUtils.getByLoginCode(user.getLoginCode());
|
||||
if (u == null){
|
||||
this.save(user);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、账号 " + user.getLoginCode() + " 导入成功");
|
||||
} else if (isUpdateSupport){
|
||||
user.setUserCode(u.getUserCode());
|
||||
this.save(user);
|
||||
successNum++;
|
||||
successMsg.append("<br/>" + successNum + "、账号 " + user.getLoginCode() + " 更新成功");
|
||||
} else {
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>" + failureNum + "、账号 " + user.getLoginCode() + " 已存在");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
String msg = "<br/>" + failureNum + "、账号 " + user.getLoginCode() + " 导入失败:";
|
||||
if (e instanceof ConstraintViolationException){
|
||||
List<String> messageList = ValidatorUtils.extractPropertyAndMessageAsList((ConstraintViolationException)e, ": ");
|
||||
for (String message : messageList) {
|
||||
msg += message + "; ";
|
||||
}
|
||||
}else{
|
||||
msg += e.getMessage();
|
||||
}
|
||||
failureMsg.append(msg);
|
||||
logger.error(msg, e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failureMsg.append(e.getMessage());
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new ServiceException(failureMsg.toString());
|
||||
}else{
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||
}
|
||||
return successMsg.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
*/
|
||||
|
||||
@@ -3,14 +3,11 @@
|
||||
*/
|
||||
package com.jeesite.modules.sys.service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.jeesite.common.entity.Page;
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.service.CrudService;
|
||||
import com.jeesite.modules.sys.dao.LogDao;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
@@ -29,20 +26,17 @@ public class LogService extends CrudService<LogDao, Log> {
|
||||
*/
|
||||
@Override
|
||||
public Page<Log> findPage(Page<Log> page, Log log) {
|
||||
|
||||
// 设置默认时间范围,默认当前月
|
||||
if (log.getCreateDate_gte() == null){
|
||||
log.setCreateDate_gte(DateUtils.setDays(new Date(), 1));
|
||||
}
|
||||
if (log.getCreateDate_lte() == null){
|
||||
log.setCreateDate_lte(DateUtils.addDays(DateUtils.addMonths(log.getCreateDate_gte(), 1), -1));
|
||||
}
|
||||
|
||||
// // 设置默认时间范围,默认当前月
|
||||
// if (log.getCreateDate_gte() == null){
|
||||
// log.setCreateDate_gte(DateUtils.setDays(new Date(), 1));
|
||||
// }
|
||||
// if (log.getCreateDate_lte() == null){
|
||||
// log.setCreateDate_lte(DateUtils.addDays(DateUtils.addMonths(log.getCreateDate_gte(), 1), -1));
|
||||
// }
|
||||
// 普通用户看自己的,管理员看全部的。
|
||||
if (!log.getCurrentUser().isAdmin()){
|
||||
log.setCreateBy(log.getCurrentUser().getUserCode());
|
||||
}
|
||||
|
||||
return super.findPage(page, log);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.Map;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -34,6 +35,7 @@ import com.jeesite.modules.sys.utils.UserUtils;
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}/sys/area")
|
||||
@ConditionalOnProperty(name="web.core.enabled", havingValue="true", matchIfMissing=true)
|
||||
public class AreaController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user