Initial commit

This commit is contained in:
unknown
2021-12-03 16:01:55 +08:00
commit d8021750cb
360 changed files with 17327 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
# 项目排除路径
/vboot-application/target/
/vboot-core/target/
/vboot-extend-bi/target/
/vboot-extend-wf/target/
+3
View File
@@ -0,0 +1,3 @@
- **初始化项目 V0.1**
- [更新] README.md、项目介绍
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 vboot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+81
View File
@@ -0,0 +1,81 @@
<div align="center"><h1 align="center">vboot-net</h1></div>
<div align="center"><h3 align="center">一个开箱即用的快速开发平台.JAVA版</h3></div>
### 🍟 概述
* 基于JAVA实现的快速开发平台。模块化插件式开发,前后端分离,开箱即用。
* 后台基于SpringBoot框架,数据库访问使用Jpa,自动生成数据库表结构。
* 前端基于Vben-Admin vxe-table框架。
* 核心模块包括:部门、用户、岗位、群组、角色、菜单、字典、日志、文件管理、定时任务等功能。
* QQ交流群:[795417789] 暂时就几个人哦,哈哈
* .NET6实现的同功能项目地址[https://gitee.com/zsvg/vboot-net](https://gitee.com/zsvg/vboot-net) 两个项目会同步开发
```
如果对您有帮助,点击右上角⭐Star⭐关注 ,感谢支持开源!
```
### 🎁 前后端一体化
将后台提供的Swagger接口直接生成对应前端的API文件,前端再也不需要手撸一个个的对应后后的API定义了。后台接口更新后,只需要重新生成一遍覆盖即可。
### 🥞 更新日志
更新日志 [点击查看](https://gitee.com/zsvg/vboot-java/CHANGELOG.md)
### 🍄 快速启动
* 准备工作:1.配置一个名为vboot-java的mysql数据库,默认账号root,密码123456(可改) 2.开启redis 可不设置密码
* 启动后台:打开项目,找到application启动类启动运行
* 启动前端方式1:前端vbenAdmin已将Build后的代码放在JAVA项目里,会随着后台启动而启动,可直接访问 `http://localhost:5000/vben.html` 预览
* 启动前端方式2:下载配套的前端UI[https://gitee.com/zsvg/vboot-vben](https://gitee.com/zsvg/vboot-vben)使用yarn构建,访问 `http://localhost:3100` 预览
### 🏀 分层说明
```
├─vboot-application ->业务应用层,在此写您具体业务代码
├─vboot-core ->框架核心层
├─vboot-extend-bi ->BI(报表与数据抽取),近期在开发中,以单独一个模块方式维护
├─vboot-extend-wf ->WF(工作流),近期在开发中,以单独一个模块方式维护
注:源码直接开发建议自己的业务代码直接写在【vboot-application】层里面,可随框架升级减少冲突。
```
### 📖 帮助文档
👉后台文档:
* SpringBoot后台框架文档 [https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)
👉前端文档:
* VbenAdmin前端业务文档 [https://vvbin.cn/next/](https://vvbin.cn/next/)
### 🍖 详细功能
1. 主控面板、控制台页面,可进行工作台,分析页,统计等功能的展示。
2. 部门管理、部门维护,支持多层级结构的树形结构。
3. 用户管理、用户维护,可设置用户部门,岗位,群组,职务,角色,数据权限等。
4. 岗位管理、岗位维护,岗位可作为用户的一个标签,岗位也可与权限等其他功能挂钩。
5. 群组管理、群组维护,群组可设置部门,用户,岗位,用于更广泛的权限设置。
6. 菜单管理、菜单目录,菜单,和按钮的维护是权限控制的基本单位。
7. 角色管理、角色绑定菜单后,可限制相关角色的人员登录系统的功能范围。
8. 字典管理、系统内各种枚举类型的维护。
9. 访问日志、用户的登录和退出日志的查看和管理。
10. 操作日志、用户的操作业务的日志的查看和管理。
11. 定时任务、定时任务的维护,通过cron表达式控制任务的执行频率。
### ⚡ 近期计划
- [ ] 文档编写
- [ ] 在线用户
- [ ] 文件存储 minio
- [ ] 集成工作流
### 🍻 贡献代码
`vboot-java` 遵循 `MIT` 开源协议,欢迎大家提交 `PR` 或 `Issue`。
### 💐 特别鸣谢
- 👉 eladmin:[https://gitee.com/elunez/eladmin](https://gitee.com/elunez/eladmin)
- 👉 ruoyi:[https://gitee.com/y_project/RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)
- 👉 vben-admin:[https://vvbin.cn/doc-next/](https://vvbin.cn/doc-next/)
- 👉 vxe-table:[https://gitee.com/xuliangzhan_admin/vxe-table](https://gitee.com/xuliangzhan_admin/vxe-table)
如果对您有帮助,您可以点右上角 💘Star💘支持一下,这样我们才有持续下去的动力,谢谢!!!
+84
View File
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zsvg</groupId>
<artifactId>vboot</artifactId>
<packaging>pom</packaging>
<version>0.1</version>
<modules>
<module>vboot-core</module>
<module>vboot-application</module>
<module>vboot-extend-bi</module>
<module>vboot-extend-wf</module>
</modules>
<!--定义属性值-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<vboot.version>0.1</vboot.version>
<spring.boot.version>2.2.13.RELEASE</spring.boot.version>
</properties>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- SpringBoot的依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--编译管理 jdk版本和字符集编码-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
<!--Maven远程仓库设置 非必要,可以删除-->
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<!--Maven远程插件库设置 非必要,可以删除-->
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
+61
View File
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>vboot</artifactId>
<groupId>com.zsvg</groupId>
<version>0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>vboot-application</artifactId>
<dependencies>
<dependency>
<groupId>com.zsvg</groupId>
<artifactId>vboot-extend-bi</artifactId>
<version>${vboot.version}</version>
</dependency>
<dependency>
<groupId>com.zsvg</groupId>
<artifactId>vboot-extend-wf</artifactId>
<version>${vboot.version}</version>
<exclusions>
<exclusion>
<groupId>com.zsvg</groupId>
<artifactId>vboot-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!-- 打包 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,56 @@
package com.abc;
import com.zsvg.vboot.common.util.lang.XstringUtil;
import com.zsvg.vboot.common.util.web.XspringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import java.net.InetAddress;
import java.net.UnknownHostException;
@EnableCaching
@SpringBootApplication
@EntityScan({"com.zsvg","com.abc"})
@ComponentScan({"com.zsvg","com.abc"})
@EnableJpaRepositories({"com.zsvg","com.abc"})
@Slf4j
//@EnableSwagger2
//@EnableRedisHttpSession(maxInactiveIntervalInSeconds=60)
public class Application {// extends SpringBootServletInitializer {
public static void main(String[] args) {
ApplicationContext app = SpringApplication.run(Application.class, args);
String[] beanDefinitionNames = app.getBeanDefinitionNames();
for (int i = 0; i < beanDefinitionNames.length; i++) {
// System.out.println(beanDefinitionNames[i]);
}
XspringUtil.setApplicationContext(app);
Environment env = app.getEnvironment();
String ip = null;
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
String port = env.getProperty("server.port");
String path = env.getProperty("server.servlet.context-path");
if (XstringUtil.isBlank(path)) {
path = "";
}
log.info("\n----------------------------------------------------------\n\t" +
"Application is running! Access URLs:\n\t" +
"Local访问网址: \t\thttp://localhost:" + port + path +"/vben.html"+ "\n\t" +
"External访问网址: \thttp://" + ip + ":" + port + path +"/vben.html"+ "\n\t");
}
}
@@ -0,0 +1,19 @@
package com.abc.demo;
import com.zsvg.vboot.common.mvc.api.RestResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("demo")
public class DemoApi {
@GetMapping
public RestResult get() {
return RestResult.ok("这里可写实际业务模块");
}
}
@@ -0,0 +1,31 @@
ldap.url=
ldap.base=
ldap.userDn=
ldap.userPwd=
ldap.referral=
ldap.domainName=
#web\u914D\u7F6E
server.port=5000
spring.servlet.multipart.max-file-size=1024
spring.servlet.multipart.max-request-size=1024
server.compression.enabled=true
server.compression.mime-types=application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css
server.compression.min-response-size=4096
app.db.type=MYSQL
app.att.path=D:/zsvg/att
#1代表session,2待办jwt token,4待办蓝凌token
app.authc.type=7
#\u6700\u5927\u8FDE\u63A5\u6570
http.maxTotal: 100
http.defaultMaxPerRoute: 20
http.connectTimeout: 1000
http.connectionRequestTimeout: 500
http.socketTimeout: 10000
http.staleConnectionCheckEnabled: true
http.validateAfterInactivity: 3000000
@@ -0,0 +1,93 @@
# 数据源配置
spring:
datasource:
druid:
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: 1
login-password: 1
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 5000
merge-sql: true
wall:
config:
multi-statement-allow: true
# driver-class-name: com.mysql.jdbc.Driver
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/vboot-java?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC&nullCatalogMeansCurrent=true
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update
open-in-view: true
banner:
location: classpath:config/banner.txt
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
ldap:
url:
base:
userDn:
userPwd:
referral:
domainName:
logging.config: classpath:config/logback.xml
zsvg:
jwt:
header: Authorization
prefix: "Bearer "
#生成accessToken用的key
akey: 6EtRVaDRFyIe5pBlBh1p6dRD+fLA5phPMyEeVkaNcEMUcpvQwZtGNby24TzuTZ4OBuXTYUaWgZqsRwROg1XWFA==
#生成refreshToken用的key
rkey: W3UZyVu0VQCGMRPvU11CqDovDUku3XASJlXLu0zFZdvUyAvXoEVrumKnz1DSBJ4O5l49Mi2Hesx7Kct4UPTL9g==
#accessToken过期时间 此处单位秒 ,默认8小时 28800
atime: 28800
#accessToken过期时间 此处单位秒 ,默认30天 3456000
rtime: 3456000
# # 在线用户key
# online-key: online-token-
# # 验证码
# code-key: code-key-
# # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期
# detect: 1800000
# # 续期时间范围,默认1小时,单位毫秒
# renew: 3600000
@@ -0,0 +1,6 @@
${AnsiColor.GREEN}
vboot V0.1 一个开箱即用的快速开发平台.JAVA版
${AnsiColor.GREEN}
${spring-boot.version}
@@ -0,0 +1,206 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
<property name="log.path" value="D:/zsvg/logs" />
<!--0. 日志格式和颜色渲染 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!-- 彩色日志格式 -->
<!--<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(-&#45;&#45;){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>-->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--1. 输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<!--<charset>UTF-8</charset>-->
</encoder>
</appender>
<!--2. 输出到文档-->
<!-- 2.1 level为 DEBUG 日志,时间滚动输出 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${log.path}/web_debug.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${log.path}/web-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 2.2 level为 INFO 日志,时间滚动输出 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${log.path}/web_info.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/web-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 2.3 level为 WARN 日志,时间滚动输出 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${log.path}/web_warn.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/web-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 2.4 level为 ERROR 日志,时间滚动输出 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
<file>${log.path}/web_error.log</file>
<!--日志文档输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/web-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文档保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文档只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender>。<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
如果未设置此属性,那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
<logger name="org.springframework.web" level="info"/>
<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
【logging.level.org.mybatis=debug logging.level.dao=debug】
-->
<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
-->
<!--<springProfile name="dev">-->
<!--<logger name="logging.level.org.hibernate" level="error"/>-->
<!--</springProfile>-->
<!-- 4. 最终的策略 -->
<!-- 4.1 开发环境:打印控制台-->
<logger name="com.abc" level="debug" additivity="false">
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO_FILE"/>
</logger>
<logger name="com.zsvg" level="debug" additivity="false">
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO_FILE"/>
</logger>
<root level="warn">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
<!--4.2 生产环境:输出到文档-->
<!--<logger name="com.abc" level="info" additivity="true">-->
<!--<appender-ref ref="CONSOLE"/>-->
<!--<appender-ref ref="INFO_FILE"/>-->
<!--</logger>-->
<!--<root level="warn">-->
<!--<appender-ref ref="WARN_FILE" />-->
<!--<appender-ref ref="ERROR_FILE" />-->
<!--</root>-->
</configuration>
@@ -0,0 +1,16 @@
#sap\u6D4B\u8BD5\u673A
jco.client.client=800
jco.client.user=xxxx
jco.client.passwd=xxxxx
jco.client.lang=zh
jco.client.ashost=10.10.10.10
jco.client.sysnr=00
#jco.client.pool_capacity=30
#jco.client.peak_limit=150
#jco.client.pool_capacity=30
#jco.client.peak_limit=150
+278
View File
@@ -0,0 +1,278 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>vboot</artifactId>
<groupId>com.zsvg</groupId>
<version>0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>vboot-core</artifactId>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<!--测试相关开始-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.databene</groupId>
<artifactId>contiperf</artifactId>
<version>2.3.4</version>
<scope>test</scope>
</dependency>
<!--测试相关结束-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--数据库相关开始-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!--数据库相关结束-->
<!--可用DATA注解自动生成get set toString等,idea需要插件支持-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--图片压缩-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<!--自动生成API文档开始-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<!--自动生成API文档结束-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.2</version>
</dependency>
<!--AUTH权限相关开始-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<!--AUTH权限相关结束-->
<!--定时调度开始-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<!--定时调度结束-->
<!--消息机制开始-->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--消息机制结束-->
<!--word,excel处理开始-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<!--word,excel处理结束-->
<!--浏览器客户端识别开始-->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>1.21</version>
</dependency>
<!--浏览器客户端识别结束-->
<!--服务器监控开始-->
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.6.2</version>
</dependency>
<!--服务器监控结束-->
<!--json包开始-->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.2.3</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<!--json包结束-->
<!--二维码-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.0</version>
</dependency>
<!--pdf水印-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.9</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!--webservice-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.7</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>1.7.2</version>
</dependency>
<!-- 解析客户端操作系统、浏览器信息 -->
<dependency>
<groupId>nl.basjes.parse.useragent</groupId>
<artifactId>yauaa</artifactId>
<version>5.23</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,16 @@
package com.zsvg.vboot.common.mvc.api;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageData {
private Integer total;
private Object items;
}
@@ -0,0 +1,57 @@
package com.zsvg.vboot.common.mvc.api;
import java.util.HashMap;
public class RestResult extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public static final String CODE_TAG = "code";
public static final String MSG_TAG = "message";
public static final String DATA_TAG = "result";
public RestResult() {
}
public RestResult(int code, String msg) {
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
}
public RestResult(int code, String msg, Object data) {
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
super.put(DATA_TAG, data);
}
public static RestResult ok() {
return RestResult.ok("操作成功");
}
public static RestResult ok(Object data) {
return RestResult.ok("操作成功", data);
}
public static RestResult ok(String msg, Object data) {
return new RestResult(0, msg, data);
}
public static RestResult error(Object data) {
return RestResult.error("操作失败", data);
}
public static RestResult error(String msg, Object data) {
return new RestResult(500, msg, data);
}
public static RestResult build(int code, String msg) {
return new RestResult(code, msg, null);
}
public static RestResult build(int code, String msg, Object data) {
return new RestResult(code, msg, data);
}
}
@@ -0,0 +1,12 @@
package com.zsvg.vboot.common.mvc.dao;
import java.sql.SQLException;
public abstract class BaseSqler {
public abstract String getSql() throws SQLException;
public abstract Object[] getParams();
}
@@ -0,0 +1,171 @@
package com.zsvg.vboot.common.mvc.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Component
public class CacheDao<T> {
private RedisTemplate<String, T> redisTemplate;
@Autowired
public CacheDao(RedisTemplate<String, T> redisTemplate) {
this.redisTemplate = redisTemplate;
}
//============================String=============================
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public T getCache(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean setCache(String key, T value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean setCache(String key, T value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
setCache(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object getHashCache(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> getHashCache(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean setHashCache(String key, Map<String, T> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// /**
// * HashSet 并设置时间
// *
// * @param key 键
// * @param map 对应多个键值
// * @param time 时间(秒)
// * @return true成功 false失败
// */
// public boolean setHashCache(String key, Map<String, T> map, long time) {
// try {
// redisTemplate.opsForHash().putAll(key, map);
// if (time > 0) {
// setExpireTime(key, time);
// }
// return true;
// } catch (Exception e) {
// e.printStackTrace();
// return false;
// }
// }
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean setHashCache(String key, String item, T value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// /**
// * 向一张hash表中放入数据,如果不存在将创建
// *
// * @param key 键
// * @param hashKey 项
// * @param value 值
// * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
// * @return true 成功 false失败
// */
// public boolean setHashCache(String key, String hashKey, T value, long time) {
// try {
// redisTemplate.opsForHash().put(key, hashKey, value);
// if (time > 0) {
// setExpireTime(key, time);
// }
// return true;
// } catch (Exception e) {
// e.printStackTrace();
// return false;
// }
// }
}
@@ -0,0 +1,51 @@
package com.zsvg.vboot.common.mvc.dao;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Dsqler extends BaseSqler{
private String deleteClause = "";
private String whereClause = "";
private List<Object> whereParameters = new ArrayList<Object>();
public Dsqler(String table)
{
this.deleteClause = "DELETE FROM " + table + " ";
}
public Dsqler addWhere(String condition, Object... params)
{
if (whereClause.length() == 0)
{
whereClause = " WHERE " + condition;
} else
{
whereClause += " AND " + condition;
}
if (params != null && params.length > 0)
{
for (Object obj : params)
{
whereParameters.add(obj);
}
}
return this;
}
public String getSql() throws SQLException {
if("".equals(whereClause)){
throw new SQLException("为防止误删,delete 语句必须要有where条件");
}
return deleteClause + whereClause;
}
public Object[] getParams()
{
return whereParameters.toArray();
}
}
@@ -0,0 +1,62 @@
package com.zsvg.vboot.common.mvc.dao;
import java.util.ArrayList;
import java.util.List;
public class Isqler extends BaseSqler
{
private String insertClause = "";
private String keyClause = "";
private String valueClause = "";
private List<Object> parameters = new ArrayList<Object>();
public Isqler(String table)
{
this.insertClause = "INSERT INTO " + table;
}
public Isqler add(String key, Object value)
{
if ("true".equals(value))
{
keyClause += key + ",";
valueClause += "?,";
parameters.add(true);
} else if ("false".equals(value))
{
keyClause += key + ",";
valueClause += "?,";
parameters.add(false);
} else
{
keyClause += key + ",";
valueClause += "?,";
parameters.add(value);
}
return this;
}
public String getSql()
{
return insertClause + "(" + keyClause.substring(0, keyClause.length() - 1) + ")" + " VALUES(" + valueClause.substring(0, valueClause.length() - 1) + ")";
}
public Object[] getParams()
{
return parameters.toArray();
}
public void testParams()
{
for (int i = 0; i < parameters.size(); i++)
{
if (i == parameters.size() - 1)
{
System.out.println(parameters.get(i) + ";");
} else
{
System.out.print(parameters.get(i) + ",");
}
}
}
}
@@ -0,0 +1,208 @@
package com.zsvg.vboot.common.mvc.dao;
import com.zsvg.vboot.module.sys.org.root.SysOrg;
import com.zsvg.vboot.common.mvc.api.PageData;
import com.zsvg.vboot.common.mvc.pojo.ZidName;
import com.zsvg.vboot.common.mvc.pojo.Zinp;
import com.zsvg.vboot.common.mvc.pojo.Ztree;
import com.zsvg.vboot.common.util.lang.XjsonUtil;
import com.zsvg.vboot.common.util.lang.XstringUtil;
import com.zsvg.vboot.common.util.web.XreqUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class JdbcDao {
@Value("${app.db.type}")
private String DB_TYPE;
public PageData findPageData(Sqler sqler) {
XreqUtil.setPageParam(sqler);
Integer count = jdbcTemplate.queryForObject(sqler.getSizeSql(), sqler.getParams(), Integer.class);
if (count == null || count == 0) {
return new PageData(0, new ArrayList<>());
}
List<Map<String, Object>> list;
if ("MYSQL".equals(DB_TYPE)) {
list = jdbcTemplate.queryForList(sqler.getMysqlPagingSql(), sqler.getParams());
} else {
list = jdbcTemplate.queryForList(sqler.getOraclePagingSql(), sqler.getParams());
}
return new PageData(count, list);
}
//--------------------------------------------------------------------------------
public List<Ztree> findTreeList(Sqler sqler) {
List<Ztree> list = jdbcTemplate.query(sqler.getSql(), sqler.getParams(), (rs, rowNum) -> {
Ztree ztree = new Ztree();
ztree.setId(rs.getString("id"));
ztree.setName(rs.getString("name"));
ztree.setPid(rs.getString("pid"));
return ztree;
});
return XjsonUtil.buildByRecursive(list);
}
public List<ZidName> findIdNameList(String sql, Object... args) {
return jdbcTemplate.query(sql, args, (rs, rowNum) -> {
ZidName ztwo = new ZidName();
ztwo.setId(rs.getString("id"));
ztwo.setName(rs.getString("name"));
return ztwo;
});
}
public List<ZidName> getIdNameListByTable(String table, String name) {
String sql = "select id,name from " + table + " where avtag = 1";
if (XstringUtil.isBlank(name)) {
return findIdNameList(sql);
} else {
return jdbcTemplate.query(sql + " and name like ?", new Object[]{"%" + name + "%"}, (rs, rowNum) -> {
ZidName ztwo = new ZidName();
ztwo.setId(rs.getString("id"));
ztwo.setName(rs.getString("name"));
return ztwo;
});
}
}
public List<ZidName> findIdNameList(Sqler sqlHelper) {
return findIdNameList((sqlHelper.getSql()), sqlHelper.getParams());
}
public List<SysOrg> findOrgList(String sql, Object... args) {
return jdbcTemplate.query(sql, args, (rs, rowNum) -> {
SysOrg sysOrg = new SysOrg();
sysOrg.setId(rs.getString("id"));
sysOrg.setName(rs.getString("name"));
return sysOrg;
});
}
public List<Zinp> findInpList(String sql, Object... args) {
return jdbcTemplate.query(sql, args, (rs, rowNum) -> {
Zinp zinp = new Zinp();
zinp.setId(rs.getString("id"));
zinp.setName(rs.getString("name"));
zinp.setPid(rs.getString("pid"));
return zinp;
});
}
public List<Zinp> findInpList(Sqler sqlHelper) {
return findInpList(sqlHelper.getSql(), sqlHelper.getParams());
}
public List<Zinp> findInpListByTable(String table) {
String sql = "select id,name,pid from " + table + " where avtag = 1";
return findInpList(sql);
}
public List<Zinp> findInpListByTable(String table, String name) {
String sql = "select id,name,pid from " + table + " where avtag = 1";
if (XstringUtil.isBlank(name)) {
return findInpList(sql);
} else {
return jdbcTemplate.query(sql + " and name like ?", new Object[]{"%" + name + "%"}, (rs, rowNum) -> new Zinp(rs.getString("id"), rs.getString("name"), rs.getString("pid")));
}
}
public List<String> findStringList(String sql, Object... args) {
return jdbcTemplate.query(sql, args, (rs, rowNum) -> rs.getString("id"));
}
public List<String> findStringList(Sqler sqler) {
return jdbcTemplate.query(sqler.getSql(), sqler.getParams(), (rs, rowNum) -> rs.getString("id"));
}
public Integer findSize(Sqler sqler) {
return jdbcTemplate.queryForObject(sqler.getSizeSql(), sqler.getParams(), Integer.class);
}
public String findOneString(String sql, Object... args) {
String str = null;
try {
str = jdbcTemplate.queryForObject(sql, args, String.class);
} catch (Exception ignored) {
}
return str;
}
public String findOneString(Sqler sqler) {
return findOneString(sqler.getSql(), sqler.getParams());
}
public Map<String, Object> findMap(Sqler sqler) {
List<Map<String, Object>> list = jdbcTemplate.queryForList(sqler.getSql(), sqler.getParams());
if (list.size() > 0) {
return list.get(0);
} else {
return null;
}
// return jdbcTemplate.queryForMap(sqler.getSql(), sqler.getParams());
}
public Map<String, Object> findMap(String sql, Object... args) {
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, args);
return list.get(0);
}
public List<Map<String, Object>> findMapList(Sqler sqler) {
return jdbcTemplate.queryForList(sqler.getSql(), sqler.getParams());
}
public List<Map<String, Object>> findMapList(String sql, Object... args) {
return jdbcTemplate.queryForList(sql, args);
}
public String findOneName(String table, String id) {
if (XstringUtil.isBlank(id)) {
return null;
} else {
return jdbcTemplate.queryForObject("select name from " + table + " where id = ?", new Object[]{id}, String.class);
}
}
//queryForObject 如果返回没结果会报错
//增删改----------------------------------------------------------------------------------
public int update(String sql, Object... args) {
return jdbcTemplate.update(sql, args);
}
public int update(BaseSqler sqler) throws SQLException {
return jdbcTemplate.update(sqler.getSql(), sqler.getParams());
}
public int[] batch(String sql, List<java.lang.Object[]> list) {
return jdbcTemplate.batchUpdate(sql, list);
}
public String getDbType() {
return DB_TYPE;
}
public JdbcTemplate getTp() {
// jdbcDao.getTp().query(sql, new Object[]{}, new BeanPropertyRowMapper<>(Qmarg.class));
return jdbcTemplate;
}
@Resource
private JdbcTemplate jdbcTemplate;
}
@@ -0,0 +1,423 @@
package com.zsvg.vboot.common.mvc.dao;
import com.zsvg.vboot.common.util.lang.XstringUtil;
import com.zsvg.vboot.config.security.pojo.Zuser;
import java.util.ArrayList;
import java.util.List;
public class Sqler
{
private String fromClause = "";
private String whereClause = "";
private String orderClause = "";
private String selectClause = "";
private String groupClause = "";
private Integer panum = 1;
private Integer pasiz = 10;
private int autoType=1;
private List<Object> parameters = new ArrayList<Object>(); // 参数清单
public Sqler()
{
}
public Sqler(String table, Integer panum, Integer pasiz)
{
this.selectClause = "SELECT t.id,t.name";
this.fromClause = " FROM " + table+" t";
if (panum != null)
{
this.panum = panum;
}
if (pasiz != null)
{
this.pasiz = pasiz;
}
}
public Sqler(String fields, String table, Integer panum, Integer pasiz)
{
this.selectClause = "SELECT " + fields;
this.fromClause = " FROM " + table+" t";
if (panum != null)
{
this.panum = panum;
}
if (pasiz != null)
{
this.pasiz = pasiz;
}
}
public Sqler(String table)
{
this.selectClause = "SELECT t.id,t.name";
this.fromClause = " FROM " + table+" t";
}
public Sqler(String fields, String table)
{
this.selectClause = "SELECT " + fields;
this.fromClause = " FROM " + table+" t";
}
public void addSelect(String fields)
{
selectClause += "," + fields;
}
public Sqler addInnerJoin(String fields, String table, String condition)
{
if (!fields.equals(""))
{
selectClause += "," + fields;
}
fromClause += " INNER JOIN " + table + " ON " + condition;
return this;
}
public Sqler addLeftJoin(String fields, String table, String condition)
{
if (!fields.equals(""))
{
selectClause += "," + fields;
}
fromClause += " Left JOIN " + table + " ON " + condition;
return this;
}
public Sqler addWhere(String condition, Object... params)
{
if (whereClause.length() == 0)
{
whereClause = " WHERE " + condition;
} else
{
whereClause += " AND " + condition;
}
if (params != null && params.length > 0)
{
for (Object obj : params)
{
parameters.add(obj);
}
}
return this;
}
public Sqler addWhere(boolean append, String condition, Object... params)
{
if (append)
{
addWhere(condition, params);
}
return this;
}
public Sqler addEqual(String name, Object value)
{
if (XstringUtil.isNotBlank(value + ""))
{
if (whereClause.length() == 0)
{
whereClause = " WHERE " + name + " = ?";
} else
{
whereClause += " AND " + name + " = ?";
}
parameters.add(value);
}
return this;
}
public Sqler addLike(String name, Object value)
{
if (XstringUtil.isNotBlank(value + ""))
{
if (whereClause.length() == 0)
{
whereClause = " WHERE " + name + " like ?";
} else
{
whereClause += " AND " + name + " like ?";
}
parameters.add("%"+(""+value).trim()+"%");
}
return this;
}
public Sqler addGtStringDate(String name, Object value)
{
if (XstringUtil.isNotBlank(value + ""))
{
if (whereClause.length() == 0)
{
whereClause = " WHERE " + name + ">=?";
} else
{
whereClause += " AND " + name + ">=?";
}
parameters.add(value);
}
return this;
}
public Sqler addGtDate(String name, Object value, String dbType)
{
if("ORACLE".equals(dbType)){
if (XstringUtil.isNotBlank(value + ""))
{
if (whereClause.length() == 0)
{
whereClause = " WHERE " + name + ">=to_date(?,'yyyy-MM-dd')";
} else
{
whereClause += " AND " + name + ">=to_date(?,'yyyy-MM-dd')";
}
parameters.add(value);
}
}else if("MYSQL".equals(dbType)){
if (XstringUtil.isNotBlank(value + ""))
{
if (whereClause.length() == 0)
{
whereClause = " WHERE unix_timestamp(" + name + ") >=unix_timestamp(?)";
} else
{
whereClause += " AND unix_timestamp(" + name + ") >=unix_timestamp(?)";
}
parameters.add(value);
}
}
return this;
}
public Sqler addLtDate(String name, Object value, String dbType)
{
if("ORACLE".equals(dbType)) {
if (XstringUtil.isNotBlank(value + "")) {
if (whereClause.length() == 0) {
whereClause = " WHERE " + name + "<to_date(?,'yyyy-MM-dd')+1";
} else {
whereClause += " AND " + name + "<to_date(?,'yyyy-MM-dd')+1";
}
parameters.add(value);
}
}else{
if (XstringUtil.isNotBlank(value + "")) {
if (whereClause.length() == 0) {
whereClause = " WHERE unix_timestamp(" + name + ") <=unix_timestamp(?)";
} else {
whereClause += " AND unix_timestamp(" + name + ") <=unix_timestamp(?)";
}
parameters.add(value+" 23:59:59");
}
}
return this;
}
public Sqler addLtStringDate(String name, Object value)
{
if (XstringUtil.isNotBlank(value + ""))
{
if (whereClause.length() == 0)
{
whereClause = " WHERE " + name + "<=?";
} else
{
whereClause += " AND " + name + "<=?";
}
parameters.add(value);
}
return this;
}
public Sqler addOrder(String propertyName)
{
if (orderClause.length() == 0)
{
orderClause = " ORDER BY " + propertyName;
} else
{
orderClause += ", " + propertyName;
}
return this;
}
public Sqler addDescOrder(String propertyName)
{
if (orderClause.length() == 0)
{
orderClause = " ORDER BY " + propertyName + " DESC";
} else
{
orderClause += ", " + propertyName + " DESC";
}
return this;
}
public Sqler addGroup(String gclause)
{
groupClause=" GROUP BY "+gclause;
return this;
}
public Sqler addJoin(String joinClause)
{
this.fromClause += " " + joinClause;
return this;
}
public Sqler addAuth(Zuser zuser, String table)
{
addJoin(" left join "+table+"_viewer vvv on vvv.id=t.id");
addJoin(" left join "+table+"_editor eee on eee.id=t.id");
if (!zuser.isAdmin())
{
addWhere("(t.crman=? or vvv.org in (" + zuser.getConds() + ") or eee.org in (" + zuser.getConds() + "))", zuser.getId());
}
return this;
}
public Sqler selectCinfo(){
addLeftJoin("oo1.name as crman,t.crtim", "sys_org oo1", "oo1.id=t.crman");
return this;
}
public Sqler selectCUinfo(){
addLeftJoin("oo1.name as crman,t.crtim", "sys_org oo1", "oo1.id=t.crman");
addLeftJoin("oo2.name as upman,t.uptim", "sys_org oo2", "oo2.id=t.upman");
return this;
}
//get and set-------------------------------------------
public String getSql()
{
return selectClause + fromClause + whereClause +groupClause+ orderClause;
}
public String getLowerCaseSql()
{
//字段转成小写
StringBuilder changeSelectClause= new StringBuilder();
String[] strArr= selectClause.split(",");
lowerCaseSelect(changeSelectClause, strArr);
changeSelectClause.deleteCharAt(changeSelectClause.length()-1);
return changeSelectClause.toString() + fromClause + whereClause+groupClause + orderClause;
}
public Sqler getNewGroupSqler(String groupClause){
Sqler sqler = new Sqler("");
sqler.fromClause=this.fromClause;
sqler.whereClause=this.whereClause;
sqler.groupClause=" group by "+groupClause;
return sqler;
}
public String getSizeSql()
{
if("".equals(groupClause)){
return "SELECT count(1)" + fromClause + whereClause;
}
else {
return "SELECT count(1) FROM (SELECT 1 " + fromClause + whereClause+groupClause+") SSZZ";
}
}
public String getMysqlPagingSql()
{
int fromIndex = pasiz * (panum - 1);
return selectClause + fromClause + whereClause+groupClause + orderClause + " limit " + fromIndex + "," + pasiz;
}
public String getOraclePagingSql()
{
int rownum = panum * pasiz;
int rn = (panum - 1) * pasiz;
return " SELECT * FROM (SELECT PPGG.*, ROWNUM RN FROM (" + selectClause + fromClause + whereClause+groupClause + orderClause + ") PPGG WHERE ROWNUM <= " + rownum + ") WHERE RN > " + rn;
// return " SELECT * FROM (SELECT PPGG.*, ROWNUM RN FROM (" + changeSelectClause.toString() + fromClause + whereClause+groupClause + orderClause + ") PPGG WHERE ROWNUM <= " + rownum + ") WHERE RN > " + rn;
}
public String getOraclePagingLowerCaseSql()
{
//字段转成小写
StringBuilder changeSelectClause= new StringBuilder();
String[] strArr= selectClause.split(",");
lowerCaseSelect(changeSelectClause, strArr);
changeSelectClause.deleteCharAt(changeSelectClause.length()-1);
//分页
int rownum = panum * pasiz;
int rn = (panum - 1) * pasiz;
return " SELECT * FROM (SELECT PPGG.*, ROWNUM RN FROM (" + changeSelectClause.toString() + fromClause + whereClause+groupClause + orderClause + ") PPGG WHERE ROWNUM <= " + rownum + ") WHERE RN > " + rn;
}
private void lowerCaseSelect(StringBuilder changeSelectClause, String[] strArr) {
for (String aStrArr : strArr) {
if(aStrArr.contains("(")&&!aStrArr.contains(")")){
changeSelectClause.append(" ").append(aStrArr);
}else{
String[] strArr2 = aStrArr.split(" ");
strArr2[strArr2.length - 1] = "\"" + strArr2[strArr2.length - 1] + "\"";
for (String aStrArr2 : strArr2) {
changeSelectClause.append(" ").append(aStrArr2);
}
}
changeSelectClause.append(",");
}
}
public Object[] getParams()
{
return parameters.toArray();
}
public void testParams()
{
for (int i = 0; i < parameters.size(); i++)
{
if (i == parameters.size() - 1)
{
System.out.println(parameters.get(i) + ";");
} else
{
System.out.print(parameters.get(i) + ",");
}
}
}
//get and set-----------------------------------------------
public Integer getPanum() {
return panum;
}
public Integer getPasiz() {
return pasiz;
}
public int getAutoType() {
return autoType;
}
public void setAutoType(int autoType) {
this.autoType = autoType;
}
public void setPanum(Integer panum) {
this.panum = panum;
}
public void setPasiz(Integer pasiz) {
this.pasiz = pasiz;
}
}
@@ -0,0 +1,84 @@
package com.zsvg.vboot.common.mvc.dao;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Usqler extends BaseSqler
{
private String updateClause = "";
private String keyClause = "";
private String whereClause = "";
private List<Object> parameters = new ArrayList<Object>(); //参数列表
private List<Object> whereParameters = new ArrayList<Object>();
public Usqler(String table)
{
this.updateClause = "UPDATE " + table + " SET ";
}
public Usqler add(String key, Object value)
{
if ("true".equals(value))
{
keyClause += key + "=?,";
parameters.add(true);
} else if ("false".equals(value))
{
keyClause += key + "=?,";
parameters.add(false);
} else
{
keyClause += key + "=?,";
parameters.add(value);
}
return this;
}
public Usqler addWhere(String condition, Object... params)
{
if (whereClause.length() == 0)
{
whereClause = " WHERE " + condition;
} else
{
whereClause += " AND " + condition;
}
if (params != null && params.length > 0)
{
for (Object obj : params)
{
whereParameters.add(obj);
}
}
return this;
}
public String getSql() throws SQLException {
if("".equals(whereClause)){
throw new SQLException("为防止误更新,update 语句必须要有where条件");
}
return updateClause + keyClause.substring(0, keyClause.length() - 1) + whereClause;
}
public Object[] getParams()
{
parameters.addAll(whereParameters);
return parameters.toArray();
}
public void testParams()
{
for (int i = 0; i < parameters.size(); i++)
{
if (i == parameters.size() - 1)
{
System.out.println(parameters.get(i) + ";");
} else
{
System.out.print(parameters.get(i) + ",");
}
}
}
}
@@ -0,0 +1,65 @@
package com.zsvg.vboot.common.mvc.entity;
import com.zsvg.vboot.module.sys.org.root.SysOrg;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.Date;
@MappedSuperclass
@Getter
@Setter
public class BaseCateEntity {
//----------------------id属性-----------------------
@Id
@Column(length = 32)
protected String id;
//----------------------权限属性-----------------------
// @ManyToMany
// @JoinTable(name = "xxx_viewer", joinColumns = {@JoinColumn(name = "id")},
// inverseJoinColumns = {@JoinColumn(name = "org")})
// private List<SysOrg> viewers;//分类可查看使用者,拥有此权限者可以创建此分类下主数据信息
//
// @ManyToMany
// @JoinTable(name = "xxx_editor", joinColumns = {@JoinColumn(name = "id")},
// inverseJoinColumns = {@JoinColumn(name = "org")})
// private List<SysOrg> editors;//分类可编辑维护者,拥有此权限者可以查看此分类下所有主数据信息
//----------------------层级属性参考-----------------------
@Column(length = 1000)
protected String tier;//层级信息
@Transient
private String pid;
@Transient
protected BaseCateEntity parent;//父类别
//----------------------norm标准属性-----------------------
@Column(length = 100)
protected String name;//名称
@Column(length = 64)
protected String label;//标签
@Column(length = 500)
protected String notes;//备注
protected Boolean avtag;//可用标记 1启用,0禁用
protected Integer ornum;//排序号
@ManyToOne
@JoinColumn(name = "crman", updatable = false)
protected SysOrg crman;//创建人
@Column(updatable = false)
protected Date crtim = new Date();//创建时间
protected Date uptim;//更新时间
@ManyToOne
@JoinColumn(name = "upman")
protected SysOrg upman;//更新人
}
@@ -0,0 +1,23 @@
package com.zsvg.vboot.common.mvc.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
@Getter
@Setter
public class BaseEntity {
@Id
@Column(length = 32)
protected String id;
@Column(length = 126)
protected String name;//名称
}
@@ -0,0 +1,53 @@
package com.zsvg.vboot.common.mvc.entity;
import com.zsvg.vboot.module.sys.org.root.SysOrg;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.Date;
@MappedSuperclass
@Getter
@Setter
public class BaseMainEntity {
//----------------------id属性-----------------------
@Id
@Column(length = 32)
protected String id;
//----------------------权限属性-----------------------
// @ManyToMany
// @JoinTable(name = "xxx_viewer", joinColumns = {@JoinColumn(name = "id")},
// inverseJoinColumns = {@JoinColumn(name = "org")})
// private List<SysOrg> viewers;//记录可查看者
//
// @ManyToMany
// @JoinTable(name = "xxx_editor", joinColumns = {@JoinColumn(name = "id")},
// inverseJoinColumns = {@JoinColumn(name = "org")})
// private List<SysOrg> editors;//记录可编辑者
//----------------------norm标准属性-----------------------
@Column(length = 126)
protected String name;//名称
protected Boolean avtag=true;//可用标记 1启用,0禁用
@ManyToOne
@JoinColumn(name = "crman", updatable = false)
protected SysOrg crman;//创建人
@Column(updatable = false)
protected Date crtim = new Date();//创建时间
@ManyToOne
@JoinColumn(name = "upman")
protected SysOrg upman;//更新人
protected Date uptim;//更新时间
}
@@ -0,0 +1,77 @@
package com.zsvg.vboot.common.mvc.exception;
public class BadConfigurationException extends RuntimeException {
/**
* Constructs a new runtime exception with {@code null} as its
* detail message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause}.
*/
public BadConfigurationException() {
super();
}
/**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public BadConfigurationException(String message) {
super(message);
}
/**
* Constructs a new runtime exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this runtime exception's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public BadConfigurationException(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a new runtime exception with the specified cause and a
* detail message of {@code (cause==null ? null : cause.toString())}
* (which typically contains the class and detail message of
* {@code cause}). This constructor is useful for runtime exceptions
* that are little more than wrappers for other throwables.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public BadConfigurationException(Throwable cause) {
super(cause);
}
/**
* Constructs a new runtime exception with the specified detail
* message, cause, suppression enabled or disabled, and writable
* stack trace enabled or disabled.
*
* @param message the detail message.
* @param cause the cause. (A {@code null} value is permitted,
* and indicates that the cause is nonexistent or unknown.)
* @param enableSuppression whether or not suppression is enabled
* or disabled
* @param writableStackTrace whether or not the stack trace should
* be writable
* @since 1.7
*/
protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
@@ -0,0 +1,21 @@
package com.zsvg.vboot.common.mvc.exception;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
@Getter
public class BadRequestException extends RuntimeException{
private Integer status = BAD_REQUEST.value();
public BadRequestException(String msg){
super(msg);
}
public BadRequestException(HttpStatus status, String msg){
super(msg);
this.status = status.value();
}
}
@@ -0,0 +1,15 @@
package com.zsvg.vboot.common.mvc.exception;
import org.springframework.util.StringUtils;
public class EntityExistException extends RuntimeException {
public EntityExistException(Class clazz, String field, String val) {
super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
}
private static String generateMessage(String entity, String field, String val) {
return StringUtils.capitalize(entity)
+ " with " + field + " "+ val + " existed";
}
}
@@ -0,0 +1,15 @@
package com.zsvg.vboot.common.mvc.exception;
import org.springframework.util.StringUtils;
public class EntityNotFoundException extends RuntimeException {
public EntityNotFoundException(Class clazz, String field, String val) {
super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
}
private static String generateMessage(String entity, String field, String val) {
return StringUtils.capitalize(entity)
+ " with " + field + " "+ val + " does not exist";
}
}
@@ -0,0 +1,34 @@
package com.zsvg.vboot.common.mvc.exception.handler;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
@Data
class ApiError {
private Integer status = 500;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime timestamp;
private String message;
private ApiError() {
timestamp = LocalDateTime.now();
}
public static ApiError error(String message){
ApiError apiError = new ApiError();
apiError.setMessage(message);
return apiError;
}
public static ApiError error(Integer status, String message){
ApiError apiError = new ApiError();
apiError.setStatus(status);
apiError.setMessage(message);
return apiError;
}
}
@@ -0,0 +1,95 @@
package com.zsvg.vboot.common.mvc.exception.handler;
import com.zsvg.vboot.common.mvc.exception.BadRequestException;
import com.zsvg.vboot.common.mvc.exception.EntityExistException;
import com.zsvg.vboot.common.mvc.exception.EntityNotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.Objects;
import static org.springframework.http.HttpStatus.NOT_FOUND;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理所有不可知的异常
*/
@ExceptionHandler(Throwable.class)
public ResponseEntity<ApiError> handleException(Throwable e){
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(e.getMessage()));
}
/**
* BadCredentialsException
*/
@ExceptionHandler(BadCredentialsException.class)
public ResponseEntity<ApiError> badCredentialsException(BadCredentialsException e){
// 打印堆栈信息
String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage();
log.error(message);
return buildResponseEntity(ApiError.error(message));
}
/**
* 处理自定义异常
*/
@ExceptionHandler(value = BadRequestException.class)
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
}
/**
* 处理 EntityExist
*/
@ExceptionHandler(value = EntityExistException.class)
public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(e.getMessage()));
}
/**
* 处理 EntityNotFound
*/
@ExceptionHandler(value = EntityNotFoundException.class)
public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(NOT_FOUND.value(),e.getMessage()));
}
/**
* 处理所有接口数据验证异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
String msg = "不能为空";
if(msg.equals(message)){
message = str[1] + ":" + message;
}
return buildResponseEntity(ApiError.error(message));
}
/**
* 统一返回
*/
private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getStatus()));
}
}
@@ -0,0 +1,18 @@
package com.zsvg.vboot.common.mvc.exception.handler;
import java.io.PrintWriter;
import java.io.StringWriter;
public class ThrowableUtil {
/**
* 获取堆栈信息
*/
public static String getStackTrace(Throwable throwable){
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
throwable.printStackTrace(pw);
return sw.toString();
}
}
}
@@ -0,0 +1,34 @@
package com.zsvg.vboot.common.mvc.others;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class MapHelper {
private Map<String,String> map;
public MapHelper(){
map = new LinkedHashMap<>();
}
public MapHelper(String field,String title){
map = new LinkedHashMap<>();
map.put("field", field);
map.put("title", title);
}
public MapHelper put(String key,String value){
map.put(key, value);
return this;
}
public Map<String,String> get(){
return map;
}
public MapHelper addTo(List list){
list.add(map);
return this;
}
}
@@ -0,0 +1,72 @@
package com.zsvg.vboot.common.mvc.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Zconn {
private String type;
private String url;
private String username;
private String passcode;
public String getSid()
{
if(isMysql())
{
return url.substring(url.lastIndexOf("/")+1).replaceAll("/","");
}
else if (isOracle())
{
return url.substring(url.lastIndexOf(":")+1);
}
else if (isDB2())
{
return url.substring(url.lastIndexOf("/")+1);
}
else{
return null;
}
}
public String getDriver(){
if(isOracle()){
return "oracle.jdbc.driver.OracleDriver";
}else if(isMysql()){
return "com.mysql.jdbc.Driver";
}else if(isMysql8()){
return "com.mysql.cj.jdbc.Driver";
}else if(isDB2()){
return "com.ibm.db2.jcc.DB2Driver";
}else{
return "暂不支持";
}
}
public boolean isOracle()
{
return "ORACLE".equals(type);
}
public boolean isMysql()
{
return "MYSQL".equals(type);
}
public boolean isMysql8()
{
return "MYSQL8".equals(type);
}
public boolean isDB2()
{
return "DB2".equals(type);
}
}
@@ -0,0 +1,47 @@
package com.zsvg.vboot.common.mvc.pojo;
public class ZidName
{
private String id;
private String name;
@Override
public String toString() {
return "ZidName{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
public ZidName(String id, String name)
{
this.id = id;
this.name = name;
}
public ZidName()
{
}
//get and set-------
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
@@ -0,0 +1,49 @@
package com.zsvg.vboot.common.mvc.pojo;
public class Zinp {
private String id;
private String name;
private String pid;
public Zinp() {
}
public Zinp(String id) {
this.id = id;
}
public Zinp(String id, String name) {
this.id = id;
this.name = name;
}
public Zinp(String id, String name, String pid) {
this.id = id;
this.name = name;
this.pid = pid;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
}
@@ -0,0 +1,23 @@
package com.zsvg.vboot.common.mvc.pojo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Data
public class Ztree {
private String id;
private String name;
@JsonIgnore
private String pid;
private List<Ztree> children;
private Map<String, Object> data;
}
@@ -0,0 +1,229 @@
package com.zsvg.vboot.common.mvc.service;
import com.zsvg.vboot.common.mvc.api.RestResult;
import com.zsvg.vboot.common.mvc.dao.JdbcDao;
import com.zsvg.vboot.common.mvc.dao.Sqler;
import com.zsvg.vboot.common.mvc.pojo.ZidName;
import com.zsvg.vboot.common.mvc.pojo.Ztree;
import com.zsvg.vboot.common.mvc.entity.BaseCateEntity;
import com.zsvg.vboot.common.mvc.api.PageData;
import com.zsvg.vboot.common.mvc.pojo.Zinp;
import com.zsvg.vboot.common.util.lang.XstringUtil;
import com.zsvg.vboot.common.util.web.XuserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Transactional(rollbackFor = Exception.class)
public abstract class BaseCateService<T extends BaseCateEntity> {
@Transactional(readOnly = true)
public PageData findPageData(Sqler sqler) {
sqler.selectCUinfo().addSelect("t.label");
sqler.addOrder("t.ornum");
return jdbcDao.findPageData(sqler);
}
@Transactional(readOnly = true)
public List<ZidName> findIdNameRes(Sqler sqler) {
return jdbcDao.findIdNameList(sqler);
}
//用户编辑时选择父类别,不能选择自己及孩子节点,否则会造成无线循环
@Transactional(readOnly = true)
public List<Zinp> inpChoose(String table, String id, String name){
Sqler sqler = new Sqler(table);
sqler.addSelect("pid");
sqler.addWhere("t.avtag = 1");
if (XstringUtil.isNotBlank(id)) {
sqler.addWhere("t.tier not like ?", "%;" + id + ";%");
sqler.addWhere("t.id <> ?", id);
}
if(XstringUtil.isNotBlank(name)){
sqler.addLike("t.name", name);
}
sqler.addOrder("t.ornum");
return jdbcDao.findInpList(sqler);
}
@Transactional(readOnly = true)
public List<Ztree> tier2Choose(String table, String id, String name){
Sqler sqler = new Sqler(table);
sqler.addSelect("pid");
sqler.addWhere("t.avtag = 1");
if (XstringUtil.isNotBlank(id)) {
sqler.addWhere("t.tier not like ?", "%;" + id + ";%");
sqler.addWhere("t.id <> ?", id);
}
if(XstringUtil.isNotBlank(name)){
sqler.addLike("t.name", name);
}
sqler.addOrder("t.ornum");
return jdbcDao.findTreeList(sqler);
}
@Transactional(readOnly = true)
public RestResult inpFind(String table){
Sqler sqlHelper = new Sqler(table);
sqlHelper.addSelect("pid");
sqlHelper.addWhere("t.avtag = 1");
sqlHelper.addOrder("t.ornum");
return RestResult.ok(jdbcDao.findInpList(sqlHelper));
}
public RestResult inpDele(String table, String id){
String sql = "select id from " + table + " where tier like ? order by tier";
List<String> stringList = jdbcDao.findStringList(sql, "%;" + id + ";%");
for (String sid : stringList) {
repo.deleteById(sid);
}
repo.deleteById(id);
return RestResult.ok();
}
public String insert(T cate) {
if(cate.getId()==null||"".equals(cate.getId())){
cate.setId(XstringUtil.getUUID());
}
if(cate.getCrman()==null){
cate.setCrman(XuserUtil.getUser());
}
if (cate.getParent() != null) {
T parent = repo.findById(cate.getParent().getId()).get();
cate.setTier(parent.getTier()+parent.getId()+ ";");
} else {
cate.setTier("null;");
}
repo.save(cate);
return cate.getId();
}
public String update(T cate){
cate.setUptim(new Date());
if(cate.getUpman()==null){
cate.setUpman(XuserUtil.getUser());
}
repo.save(cate);
return cate.getId();
}
public String update(T cate,String table){
cate.setUptim(new Date());
if(cate.getUpman()==null){
cate.setUpman(XuserUtil.getUser());
}
String newPid = "";
if(cate.getParent()!=null){
newPid=cate.getParent().getId();
}
T oldCate=repo.findById(cate.getId()).get();
String oldPid="";
if(oldCate.getParent()!=null){
oldPid =oldCate.getParent().getId();
}
String oldTier=oldCate.getTier();
if(oldPid.equals(newPid)){//如果父节点没有变,则只更新自己
// System.out.println("父节点没有变");
cate.setTier(oldTier);
repo.save(cate);
}else{//如果父节点变了,则另外需要更新自己孩子节点的tier层级
String newTier = "null;";
if(cate.getParent()!=null){
// System.out.println("父节点变成其他点了");
T newParentCate=repo.findById(cate.getParent().getId()).get();
newTier =newParentCate.getTier()+newParentCate.getId()+";";
}else{
// System.out.println("父节点变成更节点了");
}
cate.setTier(newTier);
repo.save(cate);
//更新子节点
String sql = "select id,tier as name from " + table + " where tier like ? and id<>?";
// System.out.println(sql);
List<ZidName> list = jdbcDao.findIdNameList(sql, oldTier+oldCate.getId()+";%",cate.getId());
String updateSql = "update " + table + " set tier=? where id=?";
List<Object[]> updateList = new ArrayList<Object[]>();
for (ZidName ztwo : list) {
Object[] arr = new Object[2];
arr[0] = ztwo.getName().replace(oldTier,newTier);
arr[1] = ztwo.getId();
updateList.add(arr);
}
jdbcDao.batch(updateSql, updateList);
}
return cate.getId();
}
@Autowired
protected JdbcDao jdbcDao;
protected JpaRepository<T,String> repo;
public void setRepo(JpaRepository<T,String> repo) {
this.repo = repo;
}
// public T save(T t) {
// return repo.save(t);
// }
//
// public T update(T t) {
// return repo.saveAndFlush(t);
// }
//
@Transactional(readOnly = true)
public T findOne(String id) {
return repo.findById(id).get();
}
public int delete(String[] ids) {
for (String id : ids) {
repo.deleteById(id);
}
return ids.length;
}
//
// public void deleteOne(T t) {
// repo.delete(t);
// }
//
//// public boolean exists(String id) {
//// return baseDao.exists(id);
//// }
//
// public long count() {
// return baseDao.count();
// }
//
// public List<T> findAll() {
// return baseDao.findAll();
// }
//
// public List<T> findAll(Sort sort) {
// return baseDao.findAll(sort);
// }
//
// public List<T> findAll(Specification<T> specification) {
// // TODO Auto-generated method stub
// return null;
// }
//
// public Page<T> findAll(Pageable pageable) {
// return baseDao.findAll(pageable);
// }
//
// public Page<T> findAll(Specification<T> specification, Pageable pageable) {
// // TODO Auto-generated method stub
// return null;
// }
}
@@ -0,0 +1,98 @@
package com.zsvg.vboot.common.mvc.service;
import com.zsvg.vboot.common.mvc.dao.JdbcDao;
import com.zsvg.vboot.common.mvc.dao.Sqler;
import com.zsvg.vboot.common.mvc.entity.BaseMainEntity;
import com.zsvg.vboot.common.mvc.api.PageData;
import com.zsvg.vboot.common.util.lang.XstringUtil;
import com.zsvg.vboot.common.util.web.XuserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Transactional(rollbackFor = Exception.class)
public abstract class BaseMainService<T extends BaseMainEntity> {
//---------------------------------------查询-------------------------------------
@Transactional(readOnly = true)
public PageData findPageData(Sqler sqler) {
if (sqler.getAutoType() == 1) {
sqler.selectCUinfo();
sqler.addOrder("t.crtim desc");
}
return jdbcDao.findPageData(sqler);
}
@Transactional(readOnly = true)
public List<Map<String, Object>> findMapList(Sqler sqler) {
return jdbcDao.findMapList(sqler);
}
@Transactional(readOnly = true)
public List<Map<String, Object>> findMapList(String sql, Object... args) {
return jdbcDao.findMapList(sql, args);
}
@Transactional(readOnly = true)
public boolean existsById(String id) {
return repo.existsById(id);
}
@Transactional(readOnly = true)
public T findOne(String id) {
return repo.findById(id).get();
}
@Transactional(readOnly = true)
public List<T> findAll() {
return repo.findAll();
}
//---------------------------------------增删改-------------------------------------
public T insert(T main) {
if (main.getId() == null || "".equals(main.getId())) {
main.setId(XstringUtil.getUUID());
}
main.setCrtim(new Date());
if (main.getCrman() == null) {
main.setCrman(XuserUtil.getUser());
}
return repo.save(main);
}
public int delete(String[] ids) {
for (String id : ids) {
repo.deleteById(id);
}
return ids.length;
}
public T update(T main) {
main.setUptim(new Date());
if (main.getUpman() == null) {
main.setUpman(XuserUtil.getUser());
}
return repo.save(main);
}
public T save(T t) {
return repo.save(t);
}
//---------------------------------------bean注入-------------------------------------
@Autowired
protected JdbcDao jdbcDao;
protected JpaRepository<T, String> repo;
public void setRepo(JpaRepository<T, String> repo) {
this.repo = repo;
}
}
@@ -0,0 +1,85 @@
package com.zsvg.vboot.common.mvc.service;
import com.zsvg.vboot.common.mvc.dao.JdbcDao;
import com.zsvg.vboot.common.mvc.dao.Sqler;
import com.zsvg.vboot.common.mvc.api.PageData;
import com.zsvg.vboot.common.mvc.entity.BaseEntity;
import com.zsvg.vboot.common.util.lang.XstringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
@Transactional(rollbackFor = Exception.class)
public abstract class BaseService<T extends BaseEntity> {
//---------------------------------------查询-------------------------------------
@Transactional(readOnly = true)
public PageData findPageData(Sqler sqler) {
return jdbcDao.findPageData(sqler);
}
@Transactional(readOnly = true)
public List<Map<String, Object>> findMapList(Sqler sqler) {
return jdbcDao.findMapList(sqler);
}
@Transactional(readOnly = true)
public List<Map<String, Object>> findMapList(String sql,Object... args) {
return jdbcDao.findMapList(sql,args);
}
@Transactional(readOnly = true)
public boolean existsById(String id) {
return repo.existsById(id);
}
@Transactional(readOnly = true)
public T findOne(String id) {
return repo.findById(id).get();
}
@Transactional(readOnly = true)
public List<T> findAll() {
return repo.findAll();
}
//---------------------------------------增删改-------------------------------------
public T insert(T main) {
if (main.getId() == null||"".equals(main.getId())) {
main.setId(XstringUtil.getUUID());
}
return repo.save(main);
}
public int delete(String[] ids) {
for (String id : ids) {
repo.deleteById(id);
}
return ids.length;
}
public T update(T main) {
return repo.save(main);
}
public T save(T t) {
return repo.save(t);
}
//---------------------------------------bean注入-------------------------------------
@Autowired
protected JdbcDao jdbcDao;
protected JpaRepository<T, String> repo;
public void setRepo(JpaRepository<T, String> repo) {
this.repo = repo;
}
}
@@ -0,0 +1,159 @@
package com.zsvg.vboot.common.util.file;
import com.zsvg.vboot.common.util.lang.XdateUtil;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.Iterator;
@SuppressWarnings("unchecked")
public class XexcelUtil
{
//转换列数字序号列字母序号
public static String excelColIndexToStr(int columnIndex)
{
if (columnIndex <= 0)
{
return null;
}
String columnStr = "";
columnIndex--;
do
{
if (columnStr.length() > 0)
{
columnIndex--;
}
columnStr = ((char) (columnIndex % 26 + (int) 'A')) + columnStr;
columnIndex = ((columnIndex - columnIndex % 26) / 26);
} while (columnIndex > 0);
return columnStr;
}
//---------------------以下为EXCEL复制功能-----------------
//行复制功能
public static void copyRow(Row fromRow, Row toRow, boolean copyValueFlag) {
toRow.setHeight(fromRow.getHeight());
for(Iterator cellIt = fromRow.cellIterator(); cellIt.hasNext(); ) {
Cell tmpCell = (Cell) cellIt.next();
Cell newCell = toRow.createCell(tmpCell.getColumnIndex());
copyCell(tmpCell, newCell, copyValueFlag);
}
Sheet worksheet = fromRow.getSheet();
for(int i = 0; i < worksheet.getNumMergedRegions(); i++) {
CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
if(cellRangeAddress.getFirstRow() == fromRow.getRowNum()) {
CellRangeAddress newCellRangeAddress = new CellRangeAddress(toRow.getRowNum(), (toRow.getRowNum() +
(cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow())), cellRangeAddress
.getFirstColumn(), cellRangeAddress.getLastColumn());
worksheet.addMergedRegionUnsafe(newCellRangeAddress);
}
}
}
//复制单元格 true则连同cell的内容一起复制
public static void copyCell(Cell srcCell, Cell distCell, boolean copyValueFlag) {
//样式
distCell.setCellStyle(srcCell.getCellStyle());
//评论
if(srcCell.getCellComment() != null) {
distCell.setCellComment(srcCell.getCellComment());
}
// 不同数据类型处理
CellType srcCellType = srcCell.getCellTypeEnum();
distCell.setCellType(srcCellType);
if(copyValueFlag) {
if(srcCellType == CellType.NUMERIC) {
if(DateUtil.isCellDateFormatted(srcCell)) {
distCell.setCellValue(srcCell.getDateCellValue());
} else {
distCell.setCellValue(srcCell.getNumericCellValue());
}
} else if(srcCellType == CellType.STRING) {
distCell.setCellValue(srcCell.getRichStringCellValue());
} else if(srcCellType == CellType.BLANK) {
} else if(srcCellType == CellType.BOOLEAN) {
distCell.setCellValue(srcCell.getBooleanCellValue());
} else if(srcCellType == CellType.ERROR) {
distCell.setCellErrorValue(srcCell.getErrorCellValue());
} else if(srcCellType == CellType.FORMULA) {
distCell.setCellFormula(srcCell.getCellFormula());
} else {
}
}
}
//复制单元格 true则连同cell的内容一起复制
public static HSSFCellStyle createCellStyle(HSSFWorkbook workbook,short index)
{
HSSFCellStyle style = workbook.createCellStyle();
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(index);
style.setBorderBottom(BorderStyle.HAIR);
style.setBorderTop(BorderStyle.HAIR);
style.setBorderLeft(BorderStyle.HAIR);
style.setBorderRight(BorderStyle.HAIR);
return style;
}
public static Object getCellValue(Cell cell)
{
Object back = null;
if (null != cell)
{
switch (cell.getCellType())
{
case Cell.CELL_TYPE_BLANK:
back = null;
break;
case Cell.CELL_TYPE_BOOLEAN:
back = Boolean.toString(cell.getBooleanCellValue());
break;
//数值
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell))
{
back = XdateUtil.getDate(cell.getDateCellValue());
} else
{
cell.setCellType(Cell.CELL_TYPE_STRING);
String temp = cell.getStringCellValue();
//判断是否包含小数点,如果不含小数点,则以字符串读取,如果含小数点,则转换为Double类型的字符串
if (temp.indexOf(".") > -1)
{
back = String.valueOf(new Double(temp)).trim();
} else
{
back = temp.trim();
}
}
break;
case Cell.CELL_TYPE_STRING:
back = cell.getStringCellValue().trim();
if ("".equals(back))
{
back = null;
}
break;
case Cell.CELL_TYPE_ERROR:
back = null;
break;
case Cell.CELL_TYPE_FORMULA:
cell.setCellType(Cell.CELL_TYPE_STRING);
back = cell.getStringCellValue();
break;
default:
back = null;
break;
}
}
return back;
}
}
@@ -0,0 +1,76 @@
package com.zsvg.vboot.common.util.file;
import java.io.*;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class XfileUtil
{
public static String getFileSize(long fileS)
{
String size = "";
DecimalFormat df = new DecimalFormat("#.00");
if (fileS < 1024)
{
size = df.format((double) fileS) + "B";
} else if (fileS < 1048576)
{
size = df.format((double) fileS / 1024) + "KB";
} else if (fileS < 1073741824)
{
size = df.format((double) fileS / 1048576) + "MB";
} else
{
size = df.format((double) fileS / 1073741824) + "GB";
}
return size;
}
public static void unZipFiles(File zipFile,String descDir)throws IOException
{
File pathFile = new File(descDir);
if(!pathFile.exists())
{
pathFile.mkdirs();
}
//解决zip文件中有中文目录或者中文文件
ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));
for(Enumeration entries = zip.entries(); entries.hasMoreElements();)
{
ZipEntry entry = (ZipEntry)entries.nextElement();
String zipEntryName = entry.getName();
int len2=zipEntryName.split("/")[0].length();
zipEntryName = zipEntryName.substring(len2, zipEntryName.length());
System.out.println(zipEntryName);
InputStream in = zip.getInputStream(entry);
String outPath = (descDir+zipEntryName).replaceAll("\\*", "/");;
//判断路径是否存在,不存在则创建文件路径
File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
if(!file.exists())
{
file.mkdirs();
}
//判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
if(new File(outPath).isDirectory())
{
continue;
}
//输出文件路径信息
// System.out.println(outPath);
OutputStream out = new FileOutputStream(outPath);
byte[] buf1 = new byte[1024];
int len;
while((len=in.read(buf1))>0)
{
out.write(buf1,0,len);
}
in.close();
out.close();
}
// System.out.println("******************解压完毕********************");
}
}
@@ -0,0 +1,104 @@
package com.zsvg.vboot.common.util.file;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.*;
public class XpdfUtil {
// public static void main(String[] args) throws IOException {
// setWatermark(new BufferedOutputStream(new FileOutputStream(new File("D:\\bb.pdf"))),
// new FileInputStream("D:\\aa.pdf"), "借阅借阅水印借阅水印借阅水印水印", 1);
// }
/**
* 中间或者两边水印
* @param bos 添加完水印的输出
* @param input 原PDF文件输入
* @param word 水印内容
* @param model 水印添加位置1中间,2两边
*/
public static void setWatermark(BufferedOutputStream bos, InputStream input, String word, int model) {
PdfReader reader = null;
try {
reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, bos);
PdfContentByte content;
// 创建字体,第一个参数是字体路径,itext有一些默认的字体比如说:
// BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
//2 BaseFont base = BaseFont.createFont("/msyh.ttf", BaseFont.IDENTITY_H,
// BaseFont.EMBEDDED);
//这个是为了解决linux服务器,水印乱码问题,如果是windows服务器,用第一个就可以。
// 需要指定的字体,用第2,3个写法,在resources文件夹下放置对应字体就行。
// BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
BaseFont base = BaseFont.createFont("C:/WINDOWS/Fonts/simhei.ttf", BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
// BaseFont base = BaseFont.createFont();
PdfGState gs = new PdfGState();
// 获取PDF页数
int total = reader.getNumberOfPages();
// 遍历每一页
for (int i = 0; i < total; i++) {
// 页宽度
float width = reader.getPageSize(i + 1).getWidth();
// 页高度
float height = reader.getPageSize(i + 1).getHeight();
// 内容
content = stamper.getOverContent(i + 1);
//开始写入文本
content.beginText();
//水印透明度
gs.setFillOpacity(0.2f);
content.setGState(gs);
content.setColorFill(BaseColor.LIGHT_GRAY);
//设置字体的输出位置
content.setTextMatrix(70, 200);
if (model == 1) {
//平行居中的3条水印
//字体大小
content.setFontAndSize(base, 50);
//showTextAligned 方法的参数分别是(文字对齐方式,位置内容,输出水印X轴位置,Y轴位置,旋转角度)
content.showTextAligned(Element.ALIGN_CENTER, word, width / 2, 650, 30);
content.showTextAligned(Element.ALIGN_CENTER, word, width / 2, 400, 30);
content.showTextAligned(Element.ALIGN_CENTER, word, width / 2, 150, 30);
} else {
// 左右两边个从上到下4条水印
// 水印旋转度数
float rotation = 30;
content.setFontAndSize(base, 20);
content.showTextAligned(Element.ALIGN_LEFT, word, 20, height - 50, rotation);
content.showTextAligned(Element.ALIGN_LEFT, word, 20, height / 4 * 3 - 50, rotation);
content.showTextAligned(Element.ALIGN_LEFT, word, 20, height / 2 - 50, rotation);
content.showTextAligned(Element.ALIGN_LEFT, word, 20, height / 4 - 50, rotation);
content.setFontAndSize(base, 22);
content.showTextAligned(Element.ALIGN_RIGHT, word, width - 20, height - 50, rotation);
content.showTextAligned(Element.ALIGN_RIGHT, word, width - 20, height / 4 * 3 - 50, rotation);
content.showTextAligned(Element.ALIGN_RIGHT, word, width - 20, height / 2 - 50, rotation);
content.showTextAligned(Element.ALIGN_RIGHT, word, width - 20, height / 4 - 50, rotation);
}
//结束写入文本
content.endText();
//要打图片水印的话
//Image image = Image.getInstance("c:/1.jpg");
//content.addImage(image);
}
stamper.close();
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
@@ -0,0 +1,111 @@
package com.zsvg.vboot.common.util.file;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Hashtable;
public class XqcodeUtil {
/**
* 生成包含字符串信息的二维码图片
* @param outputStream 文件输出流路径
* @param content 二维码携带信息
* @param qrCodeSize 二维码图片大小
* @param imageFormat 二维码的格式
* @throws WriterException
* @throws IOException
*/
public static boolean createQrCode(OutputStream outputStream, String content, int qrCodeSize, String imageFormat) throws WriterException, IOException{
//设置二维码纠错级别MAP
Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 矫错级别
QRCodeWriter qrCodeWriter = new QRCodeWriter();
//创建比特矩阵(位矩阵)的QR码编码的字符串
BitMatrix byteMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hintMap);
// 使BufferedImage勾画QRCode (matrixWidth 是行二维码像素点)
int matrixWidth = byteMatrix.getWidth();
BufferedImage image = new BufferedImage(matrixWidth-200, matrixWidth-200, BufferedImage.TYPE_INT_RGB);
image.createGraphics();
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, matrixWidth, matrixWidth);
// 使用比特矩阵画并保存图像
graphics.setColor(Color.BLACK);
for (int i = 0; i < matrixWidth; i++){
for (int j = 0; j < matrixWidth; j++){
if (byteMatrix.get(i, j)){
graphics.fillRect(i-100, j-100, 1, 1);
}
}
}
return ImageIO.write(image, imageFormat, outputStream);
}
public static InputStream createQrCode(String content, int qrCodeSize, String imageFormat) throws WriterException, IOException{
//设置二维码纠错级别MAP
Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 矫错级别
QRCodeWriter qrCodeWriter = new QRCodeWriter();
//创建比特矩阵(位矩阵)的QR码编码的字符串
BitMatrix byteMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hintMap);
// 使BufferedImage勾画QRCode (matrixWidth 是行二维码像素点)
int matrixWidth = byteMatrix.getWidth();
BufferedImage image = new BufferedImage(matrixWidth-200, matrixWidth-200, BufferedImage.TYPE_INT_RGB);
image.createGraphics();
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, matrixWidth, matrixWidth);
// 使用比特矩阵画并保存图像
graphics.setColor(Color.BLACK);
for (int i = 0; i < matrixWidth; i++){
for (int j = 0; j < matrixWidth; j++){
if (byteMatrix.get(i, j)){
graphics.fillRect(i-100, j-100, 1, 1);
}
}
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, imageFormat, os);
return new ByteArrayInputStream(os.toByteArray());
}
/**
* 读二维码并输出携带的信息
*/
public static void readQrCode(InputStream inputStream) throws IOException{
//从输入流中获取字符串信息
BufferedImage image = ImageIO.read(inputStream);
//将图像转换为二进制位图源
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
Result result = null ;
try {
result = reader.decode(bitmap);
} catch (ReaderException e) {
e.printStackTrace();
}
// System.out.println(result.getText());
}
/**
* 测试代码
* @throws WriterException
*/
public static void main(String[] args) throws IOException, WriterException {
createQrCode(new FileOutputStream(new File("d:\\qrcode.jpg")),"WE1231238239128sASDASDSADSDWEWWREWRERWSDFDFSDSDF123123123123213123",900,"JPEG");
readQrCode(new FileInputStream(new File("d:\\qrcode.jpg")));
}
}
@@ -0,0 +1,162 @@
package com.zsvg.vboot.common.util.lang;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class XdateUtil {
public static XMLGregorianCalendar dateToXmlDate(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
DatatypeFactory dtf = null;
try {
dtf = DatatypeFactory.newInstance();
} catch (DatatypeConfigurationException e) {
}
XMLGregorianCalendar dateType = dtf.newXMLGregorianCalendar();
dateType.setYear(cal.get(Calendar.YEAR));
//由于Calendar.MONTH取值范围为0~11,需要加1
dateType.setMonth(cal.get(Calendar.MONTH) + 1);
dateType.setDay(cal.get(Calendar.DAY_OF_MONTH));
dateType.setHour(cal.get(Calendar.HOUR_OF_DAY));
dateType.setMinute(cal.get(Calendar.MINUTE));
dateType.setSecond(cal.get(Calendar.SECOND));
return dateType;
}
public static Date xmlDate2Date(XMLGregorianCalendar cal) {
return cal.toGregorianCalendar().getTime();
}
public static String getYYYY() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
return dateFormat.format(new Date());
}
public static String getYYYYMM() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMM");
return dateFormat.format(new Date());
}
public static String getMM() {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM");
return dateFormat.format(new Date());
}
public static String getDD() {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd");
return dateFormat.format(new Date());
}
public static Date strToDate(String strDate) {
if (XstringUtil.isBlank(strDate)) {
return null;
}
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
public static Date strToDateBySap(String strDate) {
if (XstringUtil.isBlank(strDate)) {
return null;
}
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
public static String getDate() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
return dateFormat.format(new Date());
}
public static String getDate(int i) {
Calendar c = Calendar.getInstance();
int day = c.get(Calendar.DATE);
c.set(Calendar.DATE, day + i);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
return dateFormat.format(c.getTime());
}
public static String getSapDate(int i) {
Calendar c = Calendar.getInstance();
int day = c.get(Calendar.DATE);
c.set(Calendar.DATE, day + i);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
return dateFormat.format(c.getTime());
}
public static String getDate(String geshi) {
SimpleDateFormat dateFormat = new SimpleDateFormat(geshi);
return dateFormat.format(new Date());
}
public static String getDate(Date date) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
return dateFormat.format(date);
}
public static int getDifferDays(Date data1, Date date2) {
if (null == data1 || null == date2) {
return -1;
}
long intervalMilli = data1.getTime() - date2.getTime();
return (int) (intervalMilli / (24 * 60 * 60 * 1000));
}
public static int getDifferDays(String strDate1, String strDate2) {
Date date1 = strToDate(strDate1);
Date date2 = strToDate(strDate2);
if (null == date1 || null == date2) {
return -1;
}
long intervalMilli = date1.getTime() - date2.getTime();
return (int) (intervalMilli / (24 * 60 * 60 * 1000));
}
public static int getDifferDaysBySap(String strDate1, String strDate2) {
Date date1 = strToDateBySap(strDate1);
Date date2 = strToDateBySap(strDate2);
if (null == date1 || null == date2) {
return -1;
}
long intervalMilli = date1.getTime() - date2.getTime();
return (int) (intervalMilli / (24 * 60 * 60 * 1000));
}
public static String getStringDateAfterTian(String strDate, int i) {
Calendar c = Calendar.getInstance();
c.setTime(strToDateBySap(strDate));
int day = c.get(Calendar.DATE);
c.set(Calendar.DATE, day + i);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
return dateFormat.format(c.getTime());
}
public static String getMonthFirstDay() {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Calendar c = Calendar.getInstance();
c.add(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
return format.format(c.getTime());
}
public static String getMonthLastDay() {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Calendar ca = Calendar.getInstance();
ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
return format.format(ca.getTime());
}
}
@@ -0,0 +1,70 @@
package com.zsvg.vboot.common.util.lang;
import com.zsvg.vboot.common.mvc.pojo.Zinp;
import com.zsvg.vboot.common.mvc.pojo.Ztree;
import java.util.ArrayList;
import java.util.List;
public class XjsonUtil {
//使用递归方法建树
public static List<Ztree> buildByRecursive(List<Ztree> treeNodes) {
List<Ztree> trees = new ArrayList<>();
for (Ztree treeNode : treeNodes) {
if (treeNode.getPid()==null) {
trees.add(findChildrenByTier(treeNode,treeNodes));
}
}
return trees;
}
//递归查找子节点
public static Ztree findChildrenByTier(Ztree treeNode, List<Ztree> treeNodes) {
// treeNode.setChildren(new ArrayList<>());
for (Ztree it : treeNodes) {
if(treeNode.getId().equals(it.getPid())) {
if (treeNode.getChildren() == null) {
treeNode.setChildren(new ArrayList<>());
}
treeNode.getChildren().add(findChildrenByTier(it,treeNodes));
}
}
return treeNode;
}
//
public static List<Ztree> inpToTree(List<Zinp> inpList) {
List<Ztree> trees = new ArrayList<>();
for (Zinp zinp : inpList) {
if (zinp.getPid()==null) {
trees.add(findChildrenByTree(zinp,inpList));
}
}
return trees;
}
public static Ztree findChildrenByTree(Zinp zinp, List<Zinp> zinpList) {
// treeNode.setChildren(new ArrayList<>());
Ztree ztree =new Ztree();
ztree.setId(zinp.getId());
ztree.setName(zinp.getName());
for (Zinp it : zinpList) {
if(zinp.getId().equals(it.getPid())) {
if (ztree.getChildren() == null) {
ztree.setChildren(new ArrayList<>());
}
ztree.getChildren().add(findChildrenByTree(it,zinpList));
}
}
return ztree;
}
}
@@ -0,0 +1,135 @@
package com.zsvg.vboot.common.util.lang;
import java.util.HashMap;
import java.util.Map;
public class XmapUtil
{
public static String getName(String id)
{
String[] arr = id.split("/");
String back = "";
for (int i = 0; i < arr.length; i++)
{
if (!"".equals(arr[i]))
{
String mapValue = map.get(arr[i]);
if (mapValue != null)
{
back += map.get(arr[i]) + "-";
}
else
{
back += arr[i] + "-";
}
}
}
return back.substring(0, back.length() - 1);
}
public static Map<String, String> map = new HashMap<String, String>();
static
{
//a
map.put("admin", "管理员");
map.put("address", "地址");
map.put("att", "附件");
map.put("auth", "认证");
map.put("actual", "实际");
//b
map.put("bar", "块");
//c
map.put("choose", "选择");
map.put("customer", "客户");
map.put("config", "配置");
map.put("choose_data", "选择数据");
//d
map.put("demo", "样例");
//e
map.put("edit", "编辑");
map.put("edit_save", "编辑保存");
//f
map.put("file", "文件");
map.put("flow", "流程");
//g
map.put("group", "组");
//l
map.put("log", "日志");
map.put("login", "登入");
//i
map.put("index", "主页");
map.put("info", "信息");
//t
map.put("task", "任务");
map.put("type", "分类");
//m
map.put("mail", "邮箱");
map.put("main", "主信息");
map.put("move", "移动");
map.put("mobile", "移动端");
//n
map.put("node", "节点");
//o
map.put("org", "组织架构");
//p
map.put("password", "密码");
map.put("product", "产品");
map.put("project", "项目");
map.put("pp", "生产");
//q
map.put("quote", "报价");
//k
//l
map.put("line", "线");
map.put("list", "列表");
map.put("list_data", "列表数据");
map.put("list_dele", "列表删除");
map.put("layout", "扶梯排布");
//r
map.put("register", "注册");
map.put("report", "报表");
map.put("perm", "权限");
map.put("role", "角色");
map.put("scheme", "方案");
//s
map.put("save", "保存");
map.put("sd", "销售");
map.put("send", "发送");
map.put("set", "设置");
map.put("show", "展示");
map.put("stock", "股票");
//t
map.put("task", "任务");
map.put("template", "模块");
map.put("test", "测试");
map.put("tool", "工具");
map.put("tree", "树");
map.put("turn", "转换");
map.put("tree_data", "树数据");
map.put("tree_move", "树移动");
map.put("tree_remove", "树删除");
//v
map.put("view", "查看");
//w
map.put("warn", "警告");
map.put("weather", "天气");
map.put("write", "撰写");
}
}
@@ -0,0 +1,32 @@
package com.zsvg.vboot.common.util.lang;
import java.util.Random;
public class XnumberUtil {
public static double tsize = 1024L * 1024;
public static double gsize = 1024L;
public static String tranWellSize(Long space) {
if (space > tsize) {
return String.format("%.2f", space / tsize) + "T";
} else if (space > gsize) {
return String.format("%.2f", space / gsize) + "G";
} else if(space>0){
return space + "M";
}else{
return "0";
}
}
public static int getRandom6(){
int radom = new Random().nextInt(999999);
if (radom < 100000) {
radom += 100000;
}
return radom;
}
}
@@ -0,0 +1,138 @@
package com.zsvg.vboot.common.util.lang;
import com.zsvg.vboot.common.util.obj.AlterPropertyInfo;
import com.zsvg.vboot.common.util.obj.PropertyModelInfo;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
public class XreflectUtil {
public static void print(Object obj){
Field[] fields = obj.getClass().getDeclaredFields();
System.out.println("---------------------------------");
for (Field field:fields) {
field.setAccessible(true);
try {
System.out.println(field.getName()+":"+field.get(obj));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 比较两个对象属性值是否相同
* 如果不同返回修改过的属性信息
* @param oldObj
* @param newObj
* @param ignoreProperties
* @param <T>
* @return 修改过的属性字段
*/
public static <T> List<AlterPropertyInfo> getDifferentProperty(T oldObj , T newObj , String... ignoreProperties){
if (oldObj != null && newObj != null) {
// 比较全部字段
if (ignoreProperties == null || ignoreProperties.length > 0) {
if (oldObj.equals(newObj)) {
return Collections.emptyList();
}
}
List<PropertyModelInfo> oldObjectPropertyValue = getObjectPropertyValue(oldObj, ignoreProperties);
if (!CollectionUtils.isEmpty(oldObjectPropertyValue)) {
List<AlterPropertyInfo> modifiedPropertyInfos = new ArrayList<>(oldObjectPropertyValue.size());
List<PropertyModelInfo> newObjectPropertyValue = getObjectPropertyValue(newObj, ignoreProperties);
Map<String , Object> objectMap = new HashMap<>(newObjectPropertyValue.size());
// 获取新对象所有属性值
for (PropertyModelInfo propertyModelInfo : newObjectPropertyValue) {
String prnam = propertyModelInfo.getPrnam();
Object value = propertyModelInfo.getValue();
objectMap.put(prnam , value);
}
for (PropertyModelInfo propertyModelInfo : oldObjectPropertyValue) {
String prnam = propertyModelInfo.getPrnam();
Object value = propertyModelInfo.getValue();
if (objectMap.containsKey(prnam)) {
Object newValue = objectMap.get(prnam);
AlterPropertyInfo modifiedPropertyInfo = new AlterPropertyInfo();
// System.out.println("----------------------");
// System.out.println(propertyName);
// System.out.println(value);
// System.out.println(newValue);
if (value != null && newValue != null) {
if(value instanceof BigDecimal){
if ((new BigDecimal(value.toString())).compareTo(new BigDecimal(newValue.toString()))!=0) {
modifiedPropertyInfo.setPrnam(prnam);
modifiedPropertyInfo.setOlval(value);
modifiedPropertyInfo.setNeval(newValue);
modifiedPropertyInfos.add(modifiedPropertyInfo);
}
}else{
if (!(value.toString()).equals(newValue.toString())) {
modifiedPropertyInfo.setPrnam(prnam);
modifiedPropertyInfo.setOlval(value);
modifiedPropertyInfo.setNeval(newValue);
modifiedPropertyInfos.add(modifiedPropertyInfo);
}
}
}else if ((XstringUtil.isNotBlank(""+value)&& newValue == null) ||(value== null && XstringUtil.isNotBlank(""+newValue))){
modifiedPropertyInfo.setPrnam(prnam);
modifiedPropertyInfo.setOlval(value);
modifiedPropertyInfo.setNeval(newValue);
modifiedPropertyInfos.add(modifiedPropertyInfo);
}
}
}
return modifiedPropertyInfos;
}
}
return Collections.emptyList();
}
/**
* 通过反射获取对象的属性名称、getter返回值类型、属性值等信息
* @param obj
* @param ignoreProperties
* @param <T>
* @return
*/
public static <T> List<PropertyModelInfo> getObjectPropertyValue(T obj , String... ignoreProperties){
if (obj != null) {
Class<?> objClass = obj.getClass();
PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(objClass);
List<PropertyModelInfo> modelInfos = new ArrayList<>(propertyDescriptors.length);
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
Method readMethod = propertyDescriptor.getReadMethod();
String name = propertyDescriptor.getName();
if (readMethod != null && (ignoreList == null || !ignoreList.contains(name))) {
Object invoke = null;
Class<?> returnType = readMethod.getReturnType();
try {
invoke = readMethod.invoke(obj);
PropertyModelInfo propertyModelInfo = new PropertyModelInfo();
propertyModelInfo.setPrnam(name);
propertyModelInfo.setValue(invoke);
propertyModelInfo.setRetyp(returnType);
modelInfos.add(propertyModelInfo);
} catch (IllegalAccessException | InvocationTargetException e) {
System.out.println("反射获取类【"+objClass.getName()+"】方法异常,");
}
}
}
return modelInfos;
}
return Collections.emptyList();
}
}
@@ -0,0 +1,37 @@
package com.zsvg.vboot.common.util.lang;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class XregUtil {
public static boolean match(String reg, String str) {
return Pattern.matches(reg, str);
}
public static List<String> find(String reg, String str) {
Matcher matcher = Pattern.compile(reg).matcher(str);
List<String> list = new ArrayList<String>();
while (matcher.find()) {
list.add(matcher.group());
}
return list;
}
public static String find(String reg, String str, int index) {
Matcher matcher = Pattern.compile(reg).matcher(str);
if (matcher.find()) {
return matcher.group(index);
}
return null;
}
public static String findString(String reg, String str) {
String returnStr = null;
List<String> list = find(reg, str);
if (list.size() != 0)
returnStr = list.get(0);
return returnStr;
}
}
@@ -0,0 +1,149 @@
package com.zsvg.vboot.common.util.lang;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class XscanUtil
{
//从包package中获取所有的Class
public static Set<Class<?>> getClasses(String pack) {
// 第一个class类的集合
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
// 是否循环迭代
boolean recursive = true;
// 获取包的名字 并进行替换
String packageName = pack;
String packageDirName = packageName.replace('.', '/');
// 定义一个枚举的集合 并进行循环来处理这个目录下的things
Enumeration<URL> dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
// 循环迭代下去
while (dirs.hasMoreElements()) {
// 获取下一个元素
URL url = dirs.nextElement();
// 得到协议的名称
String protocol = url.getProtocol();
// 如果是以文件的形式保存在服务器上
if ("file".equals(protocol)) {
// System.err.println("file类型的扫描");
// 获取包的物理路径
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以文件的方式扫描整个包下的文件 并添加到集合中
findAndAddClassesInPackageByFile(packageName, filePath,recursive, classes);
} else if ("jar".equals(protocol)) {
// 如果是jar包文件
// 定义一个JarFile
// System.err.println("jar类型的扫描");
JarFile jar;
try {
// 获取jar
jar = ((JarURLConnection) url.openConnection())
.getJarFile();
// 从此jar包 得到一个枚举类
Enumeration<JarEntry> entries = jar.entries();
// 同样的进行循环迭代
while (entries.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/') {
// 获取后面的字符串
name = name.substring(1);
}
// 如果前半部分和定义的包名相同
if (name.startsWith(packageDirName)) {
int idx = name.lastIndexOf('/');
// 如果以"/"结尾 是一个包
if (idx != -1) {
// 获取包名 把"/"替换成"."
packageName = name.substring(0, idx)
.replace('/', '.');
}
// 如果可以迭代下去 并且是一个包
if ((idx != -1) || recursive) {
// 如果是一个.class文件 而且不是目录
if (name.endsWith(".class")
&& !entry.isDirectory()) {
// 去掉后面的".class" 获取真正的类名
String className = name.substring(
packageName.length() + 1, name
.length() - 6);
try {
// 添加到classes
classes.add(Class
.forName(packageName + '.'
+ className));
} catch (ClassNotFoundException e) {
// log
// .error("添加用户自定义视图类错误 找不到此类的.class文件");
e.printStackTrace();
}
}
}
}
}
} catch (IOException e) {
// log.error("在扫描用户定义视图时从jar包获取文件出错");
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classes;
}
//以文件的形式来获取包下的所有Class
public static void findAndAddClassesInPackageByFile(String packageName,
String packagePath, final boolean recursive, Set<Class<?>> classes) {
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 也不是目录就直接返回
if (!dir.exists() || !dir.isDirectory()) {
// log.warn("用户定义包名 " + packageName + " 下没有任何文件");
return;
}
// 如果存在 就获取包下的所有文件 包括目录
File[] dirfiles = dir.listFiles(new FileFilter() {
// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
public boolean accept(File file) {
return (recursive && file.isDirectory())
|| (file.getName().endsWith(".class"));
}
});
// 循环所有文件
for (File file : dirfiles) {
// 如果是目录 则继续扫描
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "."
+ file.getName(), file.getAbsolutePath(), recursive,
classes);
} else {
// 如果是java类文件 去掉后面的.class 只留下类名
String className = file.getName().substring(0,
file.getName().length() - 6);
try {
// 添加到集合中去
//classes.add(Class.forName(packageName + '.' + className));
//经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净
classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));
} catch (ClassNotFoundException e) {
// log.error("添加用户自定义视图类错误 找不到此类的.class文件");
e.printStackTrace();
}
}
}
}
}
@@ -0,0 +1,143 @@
package com.zsvg.vboot.common.util.lang;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class XstringUtil {
public static boolean containChinese(String str) {
Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
Matcher m = p.matcher(str);
if (m.find()) {
return true;
}
return false;
}
// public static boolean isEmpty(String str) {
// return str == null || str.length() == 0|| "null".equals(str);
// }
//
// public static boolean isNotEmpty(String str) {
// return !XstringUtil.isEmpty(str);
// }
public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0|| "null".equals(str)) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((!Character.isWhitespace(str.charAt(i)))) {
return false;
}
}
return true;
}
public static boolean isAllBlank(String str1,String str2) {
return XstringUtil.isBlank(str1)&&XstringUtil.isBlank(str2);
}
public static boolean isAllBlank(String str1,String str2,String str3) {
return XstringUtil.isBlank(str1)&&XstringUtil.isBlank(str2)&&XstringUtil.isBlank(str3);
}
public static boolean isNotBlank(String str) {
return !XstringUtil.isBlank(str);
}
public static String addWhereInCondition(String field,List<String> list){
if(list==null||list.size()==0){
return " 1=0 ";
}
StringBuilder sb=new StringBuilder(field).append(" in (");
for (String str : list) {
sb.append("'").append(str).append("',");
}
sb.setCharAt(sb.length()-1,')');
return sb.toString();
}
public static String getUUID()
{
return UUID.randomUUID().toString().replace("-", "");
}
//生成随机字母和数字,
public static String getRSID(int length) {
String val = "";
Random random = new Random();
//参数length,表示生成几位随机数
for(int i = 0; i < length; i++) {
String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
//输出字母还是数字
if( "char".equalsIgnoreCase(charOrNum) ) {
//输出是大写字母还是小写字母
// int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
val += (char)(random.nextInt(26) + 97);
} else if( "num".equalsIgnoreCase(charOrNum) ) {
val += String.valueOf(random.nextInt(10));
}
}
return val;
}
public static String getRSID4() {
return getRSID(4);
}
public static String getRSID8() {
return getRSID(8);
}
//首字母转小写
public static String toLowerfirst(String s)
{
if (Character.isLowerCase(s.charAt(0)))
{
return s;
} else
{
return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
}
}
//首字母转大写
public static String toUpperfirst(String s)
{
if (Character.isUpperCase(s.charAt(0)))
{
return s;
} else
{
return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
}
}
public static String DelZeroBefore(String str){
return str.replaceAll("^(0+)", "");
}
public static String addZeroBefore(String str, int strLength) {
int strLen = str.length();
if (strLen < strLength) {
while (strLen < strLength) {
StringBuffer sb = new StringBuffer();
sb.append("0").append(str);// 左补0
// sb.append(str).append("0");//右补0
str = sb.toString();
strLen = str.length();
}
}
return str;
}
}
@@ -0,0 +1,71 @@
package com.zsvg.vboot.common.util.lang;
import java.text.SimpleDateFormat;
import java.util.Date;
public class XtimeUtil
{
private static long lastTime;
private static long startTime;
public static String getTime()
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
}
public static void calStart()
{
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss SSS");
startTime=System.currentTimeMillis();
lastTime=startTime;
System.err.println("----"+sdf.format(new Date())+" 计时开始▼ ");
}
public static void calMid()
{
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss SSS");
long curTime=System.currentTimeMillis();
long time = curTime - lastTime;
System.err.println("----"+sdf.format(new Date())+" 中间用时■ "+time + "毫秒");
lastTime=curTime;
}
public static void calEnd()
{
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss SSS");
long curTime=System.currentTimeMillis();
long time = curTime - lastTime;
long time2 = curTime - startTime;
System.err.println("----"+sdf.format(new Date())+" 计时结束▲ "+time + "毫秒,合计:" + time2+ "毫秒");
}
public static String getTimeByDate(Date date)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
public static Boolean compare(String s1, String s2)
{
if(s1==null){
return false;
}else if(s2==null){
return true;
}
int i = s1.compareTo(s2);
if (i >= 0)
{
return true;
} else
{
return false;
}
}
public static long getTimeGap(long beforeTimeMillis)
{
return (System.currentTimeMillis() - beforeTimeMillis) / 1000;
}
}
@@ -0,0 +1,18 @@
package com.zsvg.vboot.common.util.obj;
import lombok.Data;
import java.io.Serializable;
@Data
public class AlterPropertyInfo implements Serializable {
// 对应的属性名
private String prnam;
// 未修改之前的值
private Object olval;
// 修改后的值
private Object neval;
}
@@ -0,0 +1,34 @@
package com.zsvg.vboot.common.util.obj;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class JsonDateValueProcessor implements JsonValueProcessor {
@Override
public Object processArrayValue(Object obj, JsonConfig jsonconfig) {
return process(obj);
}
@Override
public Object processObjectValue(String s, Object obj, JsonConfig jsonconfig) {
return process(obj);
}
private Object process(Object obj) {
if (obj == null) {// 如果时间为null,则返回空字串
return "";
}
if (obj instanceof Date) {
obj = new java.util.Date(((Date) obj).getTime());
}
if (obj instanceof java.util.Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
Locale.CHINA);// 格式化时间为yyyy-MM-dd类型
return sdf.format(obj);
} else {
return new Object();
}
}
}
@@ -0,0 +1,13 @@
package com.zsvg.vboot.common.util.obj;
import lombok.Data;
@Data
public class PropertyModelInfo {
//属性名
private String prnam;
// 属性值
private Object value;
// 返回值类型
private Class<?> retyp;
}
@@ -0,0 +1,145 @@
package com.zsvg.vboot.common.util.web;
import org.apache.commons.lang.StringUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class XhttpUtil {
public static String httpGetConnect(String httpUrl, String key) {
String back = "error";
if (StringUtils.isBlank(httpUrl)) {
return back;
}
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = "";
try {
URL url = new URL(httpUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "text/html");
connection.setRequestProperty("Cache-Control", "no-cache");
connection.setRequestProperty("Charsert", "UTF-8");
connection.setConnectTimeout(15000);
connection.setReadTimeout(60000);
connection.connect();
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 封装输入流is,并指定字符集
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
// 存放数据
StringBuffer sbf = new StringBuffer();
String temp = null;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
//sbf.append("\r\n");
}
result = sbf.toString();
back = result;
} else {
System.out.println("http链接错误!" + key);
back = "error";
}
} catch (Exception e) {
e.printStackTrace();
back = "error";
} finally {
// 关闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
connection.disconnect();// 关闭远程连接
}
return back;
}
public static String httpPostConnect(String httpUrl, String param, String key) {
String back = "";
if (StringUtils.isBlank(httpUrl)) {
return back;
}
HttpURLConnection connection = null;
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
try {
URL url = new URL(httpUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(15000);
connection.setReadTimeout(60000);
/** 设置是否向httpUrlConnection输出,设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个 */
// 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
connection.setDoOutput(true);
// 默认值为:true,当前向远程服务读取数据时,设置为true,该参数可有可无
connection.setDoInput(true);
// 设置是否使用缓存
connection.setUseCaches(false);
/** 设置通用的请求属性 */
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 设置传入参数的格式
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //name1=value1&name2=value2 的形式
//connection.setRequestProperty("Content-Type", "application/json;charset=utf-8"); //json格式
//connection.connect();
os = connection.getOutputStream();
if (StringUtils.isNotBlank(param)) {
os.write(param.getBytes());
}
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sbf = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
sbf.append(line);
//sbf.append("\r\n");
}
back = sbf.toString();
}
} catch (Exception e) {
e.printStackTrace();
back = "error";
} finally {
// 关闭资源
try {
if (null != br) {
br.close();
}
if (null != is) {
is.close();
}
if (null != os) {
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
connection.disconnect();// 关闭远程连接
}
return back;
}
}
@@ -0,0 +1,7 @@
package com.zsvg.vboot.common.util.web;
public class XpageUtil {
}
@@ -0,0 +1,206 @@
package com.zsvg.vboot.common.util.web;
import cn.hutool.core.convert.Convert;
import com.zsvg.vboot.common.mvc.dao.Sqler;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Enumeration;
public class XreqUtil {
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "page";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
public static void testParams(HttpServletRequest request) {
Enumeration pNames = request.getParameterNames();
while (pNames.hasMoreElements()) {
String pName = (String) pNames.nextElement();
Object pValue = request.getParameter(pName);
System.out.println(pName + ":" + pValue);
}
}
public static String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
public static void setPageParam(Sqler sqler) {
HttpServletRequest request = getRequest();
Integer pageNum = Convert.toInt(request.getParameter(PAGE_NUM));
Integer pageSize = Convert.toInt(request.getParameter(PAGE_SIZE));
if(pageNum!=null){
sqler.setPanum(pageNum);
}
if(pageSize!=null){
sqler.setPasiz(pageSize);
}
}
/**
* 获取String参数
*/
public static String getParameter(String name)
{
return getRequest().getParameter(name);
}
/**
* 获取String参数
*/
public static String getParameter(String name, String defaultValue)
{
return Convert.toStr(getRequest().getParameter(name), defaultValue);
}
/**
* 获取Integer参数
*/
public static Integer getParameterToInt(String name)
{
return Convert.toInt(getRequest().getParameter(name));
}
/**
* 获取Integer参数
*/
public static Integer getParameterToInt(String name, Integer defaultValue)
{
return Convert.toInt(getRequest().getParameter(name), defaultValue);
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name)
{
return Convert.toBool(getRequest().getParameter(name));
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name, Boolean defaultValue)
{
return Convert.toBool(getRequest().getParameter(name), defaultValue);
}
/**
* 获取request
*/
public static HttpServletRequest getRequest()
{
return getRequestAttributes().getRequest();
}
/**
* 获取response
*/
public static HttpServletResponse getResponse()
{
return getRequestAttributes().getResponse();
}
/**
* 获取session
*/
public static HttpSession getSession()
{
return getRequest().getSession();
}
public static ServletRequestAttributes getRequestAttributes()
{
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
}
/**
* 将字符串渲染到客户端
*
* @param response 渲染对象
* @param string 待渲染的字符串
* @return null
*/
public static String renderString(HttpServletResponse response, String string)
{
try
{
response.setStatus(200);
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().print(string);
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
/**
* 是否是Ajax异步请求
*
* @param request
*/
// public static boolean isAjaxRequest(HttpServletRequest request)
// {
// String accept = request.getHeader("accept");
// if (accept != null && accept.indexOf("application/json") != -1)
// {
// return true;
// }
//
// String xRequestedWith = request.getHeader("X-Requested-With");
// if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
// {
// return true;
// }
//
// String uri = request.getRequestURI();
// if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
// {
// return true;
// }
//
// String ajax = request.getParameter("__ajax");
// if (StringUtils.inStringIgnoreCase(ajax, "json", "xml"))
// {
// return true;
// }
// return false;
// }
}
@@ -0,0 +1,35 @@
package com.zsvg.vboot.common.util.web;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
public class XresUtil {
public static void downloadExcelXls(HttpServletResponse response, HSSFWorkbook workbook, String name) throws IOException
{
String fileName = URLEncoder.encode(name, "UTF-8");
response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xls");
response.setContentType("application/vnd.ms-excel");
OutputStream out = response.getOutputStream();
workbook.write(out);
out.flush();
out.close();
}
public static void downloadExcelXlsx(HttpServletResponse response, XSSFWorkbook workbook, String name) throws IOException
{
String fileName = URLEncoder.encode(name, "UTF-8");
response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xlsx");
response.setContentType("application/vnd.ms-excel");
OutputStream out = response.getOutputStream();
workbook.write(out);
out.flush();
out.close();
}
}
@@ -0,0 +1,32 @@
package com.zsvg.vboot.common.util.web;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
public class XspringUtil {
private static ApplicationContext applicationContext = null;
public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(XspringUtil.applicationContext == null){
XspringUtil.applicationContext = applicationContext;
}
}
public static ApplicationContext getApp() {
return applicationContext;
}
public static Object getBean(String name){
return getApp().getBean(name);
}
public static <T> T getBean(Class<T> clazz){
return getApp().getBean(clazz);
}
public static <T> T getBean(String name,Class<T> clazz){
return getApp().getBean(name, clazz);
}
}
@@ -0,0 +1,48 @@
package com.zsvg.vboot.common.util.web;
import com.zsvg.vboot.module.sys.org.root.SysOrg;
import com.zsvg.vboot.config.security.pojo.Zuser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
public class XuserUtil {
public static String[] admins;
public static boolean isAdmin(String usnam) {
if ("sa".equals(usnam)) {
return true;
}
for (int i = 0; i < XuserUtil.admins.length; i++) {
if (XuserUtil.admins[i].equals(usnam)) {
return true;
}
}
return false;
}
public static SysOrg getUser() {
String userId = null;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
userId = calcUserId(userId, authentication);
return new SysOrg(userId, "");
}
public static String getUserId() {
String userId = null;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
userId = calcUserId(userId, authentication);
return userId;
}
private static String calcUserId(String userId, Authentication authentication) {
if (authentication.getPrincipal() instanceof String) {
userId = (String) authentication.getPrincipal();
} else if (authentication.getPrincipal() instanceof Zuser) {
Zuser zuser = (Zuser) authentication.getPrincipal();
userId = zuser.getId();
}
return userId;
}
}
@@ -0,0 +1,51 @@
package com.zsvg.vboot.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
@Validated
@Configuration
@ConfigurationProperties(prefix = "zsvg")
public class AppConfig {
@Getter
@Setter
@Valid
private Jwt jwt = new Jwt();
@Getter
@Setter
public static class Jwt {
private String header = "Authorization"; //HTTP 报头的认证字段的 key
private String prefix = "Bearer "; //HTTP 报头的认证字段的值的前缀
private long atime = 28800L; //accessToken过期时间 此处单位秒 ,默认8小时 28800
private long rtime = 3456000L; //accessToken过期时间 此处单位秒 ,默认30天 3456000
private String akey;//生成accessToken用的key
private String rkey;//生成refreshToken用的key
//以下赞未用到
// //在线用户 key,根据 key 查询 redis 中在线用户的数据
// private String onlineKey;
//
// //验证码 key
// private String codeKey;
//
// //token 续期检查
// private Long detect;
//
// //续期时间
// private Long renew;
}
}
@@ -0,0 +1,57 @@
package com.zsvg.vboot.config.db.init;
import com.zsvg.vboot.module.sys.org.user.SysOrgUserRepo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
@Configuration
@Slf4j
public class DbInitListener implements ApplicationListener<ContextRefreshedEvent> {
/**
* 首次数据库生成后,初始化组织架构,菜单,权限角色等信息
* 增加sa,admin管理员账号及相关测试账号
* 判断依据是sys_org_user是否含有id为sa的账号
*/
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
if (!userDao.existsById("sa")) {
System.out.println("首次启动系统,正在进行数据库初始化,请耐心等待。");
sysOrgInit.initCorp();
System.out.println("1.1 初始化部门完毕");
sysOrgInit.initUser();
sysOrgInit.initZsf();
sysOrgInit.initSa();
System.out.println("1.2 初始化用户完毕");
// sysOrgInit.initPost();
// sysOrgInit.initGroup();
sysAuthInit.initMenu();
System.out.println("2.1 初始化菜单完毕");
}
} catch (Exception e) {
System.err.println("初始化出错");
e.printStackTrace();
}
}
@Autowired
private SysOrgUserRepo userDao;
@Autowired
private SysOrgInit sysOrgInit;
@Autowired
private SysAuthInit sysAuthInit;
}
@@ -0,0 +1,146 @@
package com.zsvg.vboot.config.db.init;
import com.zsvg.vboot.module.sys.auth.menu.SysAuthMenu;
import com.zsvg.vboot.module.sys.auth.menu.SysAuthMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SysAuthInit {
protected void initMenu() {
SysAuthMenu menu1 = new SysAuthMenu();
menu1.setId("Sys");
menu1.setName("系统管理");
menu1.setCode("Sys");
menu1.setComp("LAYOUT");
menu1.setPath("/sys");
menu1.setRedirect("/sys/org/user");
menu1.setOrnum(1);
menu1.setIcon("ant-design:setting-outlined");
menu1.setAvtag(true);
menu1.setShtag(true);
menu1.setType("D");
menuService.insert(menu1);
SysAuthMenu menu11 = new SysAuthMenu();
menu11.setId("SysOrg");
menu11.setName("组织架构");
menu11.setCode("SysOrg");
menu11.setComp("LAYOUT");
menu11.setPath("/sys/org");
menu11.setRedirect("/sys/org/user");
menu11.setOrnum(1);
menu11.setIcon("ant-design:partition-outlined");
menu11.setPid("Sys");
menu11.setAvtag(true);
menu11.setShtag(true);
menu11.setType("D");
menuService.insert(menu11);
SysAuthMenu menu111 = new SysAuthMenu();
menu111.setId("SysOrgDept");
menu111.setName("部门管理");
menu111.setCode("SysOrgDept");
menu111.setPath("/sys/org/dept");
menu111.setComp("/sys/org/dept/index.vue");
menu111.setOrnum(1);
menu111.setPid("SysOrg");
menu111.setCatag(false);
menu111.setAvtag(true);
menu111.setShtag(true);
menu111.setType("M");
menuService.insert(menu111);
SysAuthMenu menu112 = new SysAuthMenu();
menu112.setId("SysOrgUser");
menu112.setName("用户管理");
menu112.setCode("SysOrgUser");
menu112.setPath("/sys/org/user");
menu112.setComp("/sys/org/user/index.vue");
menu112.setOrnum(2);
menu112.setPid("SysOrg");
menu112.setCatag(false);
menu112.setAvtag(true);
menu112.setShtag(true);
menu112.setType("M");
menuService.insert(menu112);
SysAuthMenu menu113 = new SysAuthMenu();
menu113.setId("SysOrgPost");
menu113.setName("岗位管理");
menu113.setCode("SysOrgPost");
menu113.setPath("/sys/org/post");
menu113.setComp("/sys/org/post/index.vue");
menu113.setOrnum(3);
menu113.setPid("SysOrg");
menu113.setCatag(false);
menu113.setAvtag(true);
menu113.setShtag(true);
menu113.setType("M");
menuService.insert(menu113);
SysAuthMenu menu114 = new SysAuthMenu();
menu114.setId("SysOrgGroup");
menu114.setName("群组管理");
menu114.setCode("SysOrgGroup");
menu114.setPath("/sys/org/group");
menu114.setComp("/sys/org/group/index.vue");
menu114.setOrnum(4);
menu114.setPid("SysOrg");
menu114.setCatag(false);
menu114.setAvtag(true);
menu114.setShtag(true);
menu114.setType("M");
menuService.insert(menu114);
SysAuthMenu menu12 = new SysAuthMenu();
menu12.setId("SysAuth");
menu12.setName("权限管理");
menu12.setCode("SysAuth");
menu12.setComp("LAYOUT");
menu12.setPath("/sys/auth");
menu12.setRedirect("/sys/auth/menu");
menu12.setOrnum(2);
menu12.setIcon("ant-design:safety-certificate-outlined");
menu12.setPid("Sys");
menu12.setAvtag(true);
menu12.setShtag(true);
menu12.setType("D");
menuService.insert(menu12);
SysAuthMenu menu121 = new SysAuthMenu();
menu121.setId("SysAuthMenu");
menu121.setName("菜单管理");
menu121.setCode("SysAuthMenu");
menu121.setPath("/sys/auth/menu");
menu121.setComp("/sys/auth/menu/index.vue");
menu121.setOrnum(1);
menu121.setPid("SysAuth");
menu121.setCatag(false);
menu121.setAvtag(true);
menu121.setShtag(true);
menu121.setType("M");
menuService.insert(menu121);
SysAuthMenu menu122 = new SysAuthMenu();
menu122.setId("SysAuthRole");
menu122.setName("角色管理");
menu122.setCode("SysAuthRole");
menu122.setPath("/sys/auth/role");
menu122.setComp("/sys/auth/role/index.vue");
menu122.setOrnum(1);
menu122.setPid("SysAuth");
menu122.setCatag(false);
menu122.setAvtag(true);
menu122.setShtag(true);
menu122.setType("M");
menuService.insert(menu122);
}
@Autowired
private SysAuthMenuService menuService;
}
@@ -0,0 +1,317 @@
package com.zsvg.vboot.config.db.init;
import com.zsvg.vboot.common.mvc.dao.JdbcDao;
import com.zsvg.vboot.common.util.lang.XstringUtil;
import com.zsvg.vboot.module.sys.org.dept.SysOrgDeptService;
import com.zsvg.vboot.module.sys.org.root.SysOrg;
import com.zsvg.vboot.module.sys.org.user.SysOrgUser;
import com.zsvg.vboot.module.sys.org.user.SysOrgUserService;
import com.zsvg.vboot.module.sys.org.dept.SysOrgDept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class SysOrgInit {
//公司及子公司初始化
protected void initCorp() throws Exception {
List<SysOrgDept> deptList = new ArrayList<>();
initDept(deptList,"刘", "LIU",1);
initDept(deptList,"陈", "CHEN",2);
initDept(deptList,"张", "ZHANG",3);
initDept(deptList,"李", "LI",4);
initDept(deptList,"王", "WANG",5);
initDept(deptList,"赵", "ZHAO",6);
initDept(deptList,"孙", "SUN",7);
initDept(deptList,"周", "ZHOU",8);
initDept(deptList,"吴", "WU",9);
initDept(deptList,"郑", "ZHENG",10);
deptService.insertAll(deptList);
}
//部门初始化
private void initDept(List<SysOrgDept> deptList,String name, String id,Integer ornum) throws Exception {
SysOrgDept corp = new SysOrgDept();
corp.setType(1);
corp.setId(id);
corp.setName(name + "家科技");
corp.setLabel(id);
corp.setOrnum(ornum);
corp.setAvtag(true);
corp.setTier("x"+id+"x");
deptList.add(corp);
SysOrgDept dept1 = new SysOrgDept();
dept1.setType(2);
dept1.setId(id + "-1");
dept1.setName(name + "一总金办");
dept1.setLabel(id);
dept1.setParent(new SysOrg(id));
dept1.setOrnum(1);
dept1.setAvtag(true);
dept1.setTier("x"+id+"x"+id + "-1"+"x");
deptList.add(dept1);
SysOrgDept dept2 = new SysOrgDept();
dept2.setType(2);
dept2.setId(id + "-2");
dept2.setName(name + "二人事部");
dept2.setLabel(id);
dept2.setParent(new SysOrg(id));
dept2.setOrnum(2);
dept2.setAvtag(true);
dept2.setTier("x"+id+"x"+id + "-2"+"x");
deptList.add(dept2);
SysOrgDept dept3 = new SysOrgDept();
dept3.setType(2);
dept3.setId(id + "-3");
dept3.setName(name + "三销售部");
dept3.setLabel(id);
dept3.setParent(new SysOrg(id));
dept3.setOrnum(3);
dept3.setAvtag(true);
dept3.setTier("x"+id+"x"+id + "-3"+"x");
deptList.add(dept3);
SysOrgDept dept4 = new SysOrgDept();
dept4.setType(2);
dept4.setId(id + "-4");
dept4.setName(name + "四财务部");
dept4.setLabel(id);
dept4.setParent(new SysOrg(id));
dept4.setOrnum(4);
dept4.setAvtag(true);
dept4.setTier("x"+id+"x"+id + "-4"+"x");
deptList.add(dept4);
SysOrgDept dept5 = new SysOrgDept();
dept5.setType(2);
dept5.setId(id + "-5");
dept5.setName(name + "五采购部");
dept5.setLabel(id);
dept5.setParent(new SysOrg(id));
dept5.setOrnum(5);
dept5.setAvtag(true);
dept5.setTier("x"+id+"x"+id + "-5"+"x");
deptList.add(dept5);
SysOrgDept dept6 = new SysOrgDept();
dept6.setType(2);
dept6.setId(id + "-6");
dept6.setName(name + "六技术部");
dept6.setLabel(id);
dept6.setParent(new SysOrg(id));
dept6.setOrnum(6);
dept6.setAvtag(true);
dept6.setTier("x"+id+"x"+id + "-6"+"x");
deptList.add(dept6);
SysOrgDept dept7 = new SysOrgDept();
dept7.setType(2);
dept7.setId(id + "-7");
dept7.setName(name + "七制造部");
dept7.setLabel(id);
dept7.setParent(new SysOrg(id));
dept7.setOrnum(7);
dept7.setAvtag(true);
dept7.setTier("x"+id+"x"+id + "-7"+"x");
deptList.add(dept7);
SysOrgDept dept8 = new SysOrgDept();
dept8.setType(2);
dept8.setId(id + "-8");
dept8.setName(name + "八法务部");
dept8.setLabel(id);
dept8.setParent(new SysOrg(id));
dept8.setOrnum(8);
dept8.setAvtag(true);
dept8.setTier("x"+id+"x"+id + "-8"+"x");
deptList.add(dept8);
SysOrgDept dept9 = new SysOrgDept();
dept9.setType(2);
dept9.setId(id + "-9");
dept9.setName(name + "九信息部");
dept9.setLabel(id);
dept9.setParent(new SysOrg(id));
dept9.setOrnum(9);
dept9.setAvtag(true);
dept9.setTier("x"+id+"x"+id + "-9"+"x");
deptList.add(dept9);
for (int i = 1; i <= 50; i++) {
String RSID8= XstringUtil.getRSID8();
SysOrgDept xdept = new SysOrgDept();
xdept.setType(2);
xdept.setId(id + "--"+i);
xdept.setName(RSID8);
xdept.setLabel(id);
xdept.setParent(new SysOrg(id+"-"+(i%10==0?1:i%10)));
xdept.setAvtag(true);
xdept.setTier("x"+id+"x"+id+"-"+(i%10==0?1:i%10)+"x"+id + "--"+i+"x");
deptList.add(xdept);
}
}
protected void initUser() {
List<SysOrgUser> userList = new ArrayList<>();
initUser(userList,"刘", "liu", "LIU");
initUser(userList,"陈", "c", "CHEN");
initUser(userList,"张", "z", "ZHANG");
initUser(userList,"李", "l", "LI");
initUser(userList,"王", "w", "WANG");
initUser(userList,"赵", "zhao", "ZHAO");
initUser(userList,"孙", "s", "SUN");
initUser(userList,"周", "zhou", "ZHOU");
initUser(userList,"吴", "wu", "WU");
initUser(userList,"郑", "zheng", "ZHENG");
userService.insertAll(userList);
}
private void initUser(List<SysOrgUser> userList,String name, String id, String pid) {
SysOrgUser user0 = new SysOrgUser();
user0.setId(id+"lao");
user0.setUsnam(id);
user0.setName(name + "老");
user0.setDept(new SysOrg(pid));
user0.setPacod("1");//1
user0.setAvtag(true);
user0.setTier("x"+pid+"x"+id+"lao");
userList.add(user0);
for (int i = 1; i <= 9; i++) {
SysOrgUser userx = new SysOrgUser();
userx.setId(id + i);
userx.setUsnam(id + i);
userx.setName(name + numChange("" + i));
userx.setDept(new SysOrg(pid + "-" + i));
userx.setOrnum(i);
userx.setPacod("1");//1
userx.setAvtag(true);
userx.setTier("x"+pid+"x"+pid + "-" + i+"x"+id + i+"x");
userList.add(userx);
for (int j = 1; j <= 9; j++) {
SysOrgUser usery = new SysOrgUser();
usery.setId(id + i + j);
usery.setUsnam(id + i + j);
usery.setName(name + numChange("" + i) + numChange("" + j));
usery.setDept(new SysOrg(pid + "-" + i));
usery.setOrnum(j);
usery.setPacod("1");//1
usery.setAvtag(true);
usery.setTier("x"+pid+"x"+pid + "-" + i+"x"+id + i + j+"x");
userList.add(usery);
}
}
}
protected void initZsf() {
SysOrgDept dept1 = new SysOrgDept();
dept1.setType(2);
dept1.setId("ZHANG-3-1");
dept1.setName("张三销售一室");
dept1.setLabel("ZHANG");
dept1.setParent(new SysOrg("ZHANG-3"));
dept1.setOrnum(1);
dept1.setAvtag(true);
dept1.setTier("xZHANGxZHANG-3xZHANG-3-1x");
deptService.insert(dept1);
SysOrgDept dept2 = new SysOrgDept();
dept2.setType(2);
dept2.setId("ZHANG-3-2");
dept2.setName("张三销售二室");
dept2.setLabel("ZHANG");
dept2.setParent(new SysOrg("ZHANG-3"));
dept2.setOrnum(1);
dept2.setAvtag(true);
dept2.setTier("xZHANGxZHANG-3xZHANG-3-2x");
deptService.insert(dept2);
SysOrgUser user4 = new SysOrgUser();
user4.setId("zsf");
user4.setUsnam("zsf");
user4.setName("张三丰");
user4.setDept(new SysOrg("ZHANG-3-2"));
user4.setOrnum(1);
user4.setPacod("1");
user4.setAvtag(true);
user4.setTier("xZHANGxZHANG-3xZHANG-3-2xzsfx");
userService.insert(user4);
}
protected void initSa() {
SysOrgUser user = new SysOrgUser();
user.setId("sa");
user.setUsnam("sa");
user.setName("管理员");
user.setPacod("1");
user.setAvtag(true);
user.setTier("xsax");
userService.insert(user);
SysOrgUser user2 = new SysOrgUser();
user2.setId("vben");
user2.setUsnam("vben");
user2.setName("小维");
user2.setPacod("123456");
user2.setAvtag(true);
user2.setTier("xvbenx");
userService.insert(user2);
}
private String numChange(String num) {
switch (num) {
case "1":
return "一";
case "2":
return "二";
case "3":
return "三";
case "4":
return "四";
case "5":
return "五";
case "6":
return "六";
case "7":
return "七";
case "8":
return "八";
case "9":
return "九";
case "10":
return "十";
}
return "零";
}
//
// //岗位初始化
// private void initPost() {
//
// }
//
// //组织架构组初始化
// private void initGroup() {
//
// }
@Autowired
private JdbcDao jdbcDao;
@Autowired
private SysOrgDeptService deptService;
@Autowired
private SysOrgUserService userService;
}
@@ -0,0 +1,50 @@
package com.zsvg.vboot.config.dbx.ldap;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class LdapConfig {
@Value("${ldap.url}")
private String ldapUrl;
@Value("${ldap.base}")
private String ldapBase;
@Value("${ldap.userDn}")
private String ldapUserDn;
@Value("${ldap.userPwd}")
private String ldapUserPwd;
@Value("${ldap.referral}")
private String ldapReferral;
@Bean
public LdapTemplate ldapTemplate() {
return new LdapTemplate(contextSourceTarget());
}
@Bean
public LdapContextSource contextSourceTarget() {
LdapContextSource ldapContextSource = new LdapContextSource();
ldapContextSource.setUrl(ldapUrl);
ldapContextSource.setBase(ldapBase);
ldapContextSource.setUserDn(ldapUserDn);
ldapContextSource.setPassword(ldapUserPwd);
ldapContextSource.setReferral(ldapReferral);
Map<String, Object> config = new HashMap();
config.put("java.naming.ldap.attributes.binary", "objectGUID");
// config.put("com.sun.jndi.ldap.read.timeout","3000");
ldapContextSource.setPooled(false);
ldapContextSource.setBaseEnvironmentProperties(config);
return ldapContextSource;
}
}
@@ -0,0 +1,197 @@
package com.zsvg.vboot.config.dbx.redis;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import com.zsvg.vboot.common.util.lang.XstringUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Configuration
@EnableCaching
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport {
/**
* 设置 redis 数据默认过期时间,默认2小时
* 设置@cacheable 序列化方式
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.
SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(6));
return configuration;
}
@SuppressWarnings("all")
@Bean(name = "redisTemplate")
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//序列化
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// 全局开启AutoType,这里方便开发,使用全局的方式
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 建议使用这种方式,小范围指定白名单
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain");
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
/**
* 自定义缓存key生成策略,默认将使用该策略
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
Map<String, Object> container = new HashMap<>(3);
Class<?> targetClassClass = target.getClass();
// 类地址
container.put("class", targetClassClass.toGenericString());
// 方法名称
container.put("methodName", method.getName());
// 包名称
container.put("package", targetClassClass.getPackage());
// 参数列表
for (int i = 0; i < params.length; i++) {
container.put(String.valueOf(i), params[i]);
}
// 转为JSON字符串
String jsonString = JSON.toJSONString(container);
// 做SHA256 Hash计算,得到一个SHA256摘要作为Key
return DigestUtils.sha256Hex(jsonString);
};
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
return new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
log.error("Redis occur handleCacheClearError:", e);
}
};
}
}
/**
* Value 序列化
*
* @param <T>
* @author /
*/
class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private final Class<T> clazz;
FastJsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
}
@Override
public T deserialize(byte[] bytes) {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, StandardCharsets.UTF_8);
return JSON.parseObject(str, clazz);
}
}
/**
* 重写序列化器
*
* @author /
*/
class StringRedisSerializer implements RedisSerializer<Object> {
private final Charset charset;
StringRedisSerializer() {
this(StandardCharsets.UTF_8);
}
private StringRedisSerializer(Charset charset) {
Assert.notNull(charset, "Charset must not be null!");
this.charset = charset;
}
@Override
public String deserialize(byte[] bytes) {
return (bytes == null ? null : new String(bytes, charset));
}
@Override
public byte[] serialize(Object object) {
String string = JSON.toJSONString(object);
if (XstringUtil.isBlank(string)) {
return null;
}
string = string.replace("\"", "");
return string.getBytes(charset);
}
}
@@ -0,0 +1,693 @@
package com.zsvg.vboot.config.dbx.redis;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Component
@SuppressWarnings({"unchecked", "all"})
public class RedisHandler {
private static final Logger log = LoggerFactory.getLogger(RedisHandler.class);
private RedisTemplate<Object, Object> redisTemplate;
// @Value("${jwt.online-key}")
private String onlineKey="online-key";
public RedisHandler(RedisTemplate<Object, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
return true;
}
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @param timeUnit 单位
*/
public boolean expire(String key, long time, TimeUnit timeUnit) {
try {
if (time > 0) {
redisTemplate.expire(key, time, timeUnit);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
return true;
}
/**
* 根据 key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(Object key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 查找匹配key
*
* @param pattern key
* @return /
*/
public List<String> scan(String pattern) {
ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection rc = Objects.requireNonNull(factory).getConnection();
Cursor<byte[]> cursor = rc.scan(options);
List<String> result = new ArrayList<>();
while (cursor.hasNext()) {
result.add(new String(cursor.next()));
}
try {
RedisConnectionUtils.releaseConnection(rc, factory);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return result;
}
/**
* 分页查询 key
*
* @param patternKey key
* @param page 页码
* @param size 每页数目
* @return /
*/
public List<String> findKeysForPage(String patternKey, int page, int size) {
ScanOptions options = ScanOptions.scanOptions().match(patternKey).build();
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection rc = Objects.requireNonNull(factory).getConnection();
Cursor<byte[]> cursor = rc.scan(options);
List<String> result = new ArrayList<>(size);
int tmpIndex = 0;
int fromIndex = page * size;
int toIndex = page * size + size;
while (cursor.hasNext()) {
if (tmpIndex >= fromIndex && tmpIndex < toIndex) {
result.add(new String(cursor.next()));
tmpIndex++;
continue;
}
// 获取到满足条件的数据后,就可以退出了
if (tmpIndex >= toIndex) {
break;
}
tmpIndex++;
cursor.next();
}
try {
RedisConnectionUtils.releaseConnection(rc, factory);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return result;
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
public void del(String... keys) {
if (keys != null && keys.length > 0) {
if (keys.length == 1) {
boolean result = redisTemplate.delete(keys[0]);
log.debug("--------------------------------------------");
log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(",结果:").append(result).toString());
log.debug("--------------------------------------------");
} else {
Set<Object> keySet = new HashSet<>();
for (String key : keys) {
keySet.addAll(redisTemplate.keys(key));
}
long count = redisTemplate.delete(keySet);
log.debug("--------------------------------------------");
log.debug("成功删除缓存:" + keySet.toString());
log.debug("缓存删除数量:" + count + "个");
log.debug("--------------------------------------------");
}
}
}
// ============================String=============================
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 批量获取
*
* @param keys
* @return
*/
public List<Object> multiGet(List<String> keys) {
List list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys));
List resultList = Lists.newArrayList();
Optional.ofNullable(list).ifPresent(e -> list.forEach(ele -> Optional.ofNullable(ele).ifPresent(resultList::add)));
return resultList;
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间
* @param timeUnit 类型
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time, TimeUnit timeUnit) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, timeUnit);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
// ================================Map=================================
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
// ============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
}
}
// ===============================list=================================
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return /
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
return redisTemplate.opsForList().remove(key, count, value);
} catch (Exception e) {
log.error(e.getMessage(), e);
return 0;
}
}
/**
* @param prefix 前缀
* @param ids id
*/
public void delByKeys(String prefix, Set<Long> ids) {
Set<Object> keys = new HashSet<>();
for (Long id : ids) {
keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString()));
}
long count = redisTemplate.delete(keys);
// 此处提示可自行删除
log.debug("--------------------------------------------");
log.debug("成功删除缓存:" + keys.toString());
log.debug("缓存删除数量:" + count + "个");
log.debug("--------------------------------------------");
}
}
@@ -0,0 +1,116 @@
package com.zsvg.vboot.config.security;
import com.zsvg.vboot.config.dbx.redis.RedisHandler;
import com.zsvg.vboot.config.security.authn.AuthnFailedHandler;
import com.zsvg.vboot.config.security.authz.AuthzDeniedHandler;
import com.zsvg.vboot.config.security.jwt.JwtFilterAdapter;
import com.zsvg.vboot.config.security.jwt.JwtHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.Collections;
@Configuration
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//1.禁用JWT登录无关的相关功能
http.headers().frameOptions().disable().and()
.formLogin(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.logout(AbstractHttpConfigurer::disable)
.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
//2.跨域处理
http.cors(cors -> cors.configurationSource(corsConfigurationSource()));
//3.启用JWT过滤器
http.apply(securityConfigurerAdapter());
//4.过滤器异常与授权失败处理
http.exceptionHandling()
.authenticationEntryPoint(authnFailedHandler)
.accessDeniedHandler(authzDeniedHandler);
//5.授权配置
http.authorizeRequests(authorizeRequests -> authorizeRequests
.antMatchers("/gen/**").permitAll()//gen通用的请求直接放行
// .antMatchers("/sys/**").hasRole("ADMIN")//sys开头的需要管理员权限
// .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()//放行OPTIONS请求
.antMatchers("/**").access("@authzHandler.hasPermission(request, authentication)")//其他请求统一认证
// .antMatchers("/getUserInfo").hasRole("xxx")
.anyRequest().authenticated());
}
//<<-------------------------------2.跨域处理-------------------------------
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
// if (environment.acceptsProfiles(Profiles.of("dev"))) {
// configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3100"));
// } else {
// configuration.setAllowedOrigins(Collections.singletonList("https://uaa.imooc.com"));
// }
// configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3100"));
configuration.setAllowedOrigins(Collections.singletonList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Collections.singletonList("*"));
configuration.addExposedHeader("X-Authenticate");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
//>>
//<<-------------------------------3.启用JWT过滤器-------------------------------
private final JwtHandler jwtHandler;
private final RedisHandler redisHandler;
//JwtFilter 如果通过@Component 注解注入,则web.ignoring().antMatchers 不起作用,还是会被拦截过滤
private JwtFilterAdapter securityConfigurerAdapter() {
return new JwtFilterAdapter(jwtHandler, redisHandler);
}
//>>
//<<-------------------------------4.过滤器异常与授权失败处理-------------------------------
private final AuthzDeniedHandler authzDeniedHandler;//解决认证过的用户访问无权限资源时的异常
private final AuthnFailedHandler authnFailedHandler;//解决匿名用户访问无权限资源时的异常
//>>
//<<-------------------------------X.其他配置-------------------------------
//配置security忽略的请求与资源
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/**","/assets/**","/druid/**","/login", "/pub/**","/index.html","/vben.html","/favicon.ico","/resource/**","/_app.config.js");
}
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.authenticationProvider(ssLoginProvider);
//// auth.userDetailsService(ssUserDetailsService).passwordEncoder( passwordEncoder());
// }
// @Bean
// public PasswordEncoder passwordEncoder() {
// return new BCryptPasswordEncoder();
// }
//authn是认证相关的类,authz是授权相关的类
}
@@ -0,0 +1,152 @@
package com.zsvg.vboot.config.security.authn;
import cn.hutool.core.util.IdUtil;
import com.zsvg.vboot.common.mvc.api.RestResult;
import com.zsvg.vboot.common.mvc.dao.JdbcDao;
import com.zsvg.vboot.config.AppConfig;
import com.zsvg.vboot.module.sys.org.user.SysOrgUserService;
import com.zsvg.vboot.config.dbx.redis.RedisHandler;
import com.zsvg.vboot.config.security.jwt.JwtHandler;
import com.zsvg.vboot.config.security.pojo.Duser;
import com.zsvg.vboot.config.security.pojo.Zmenu;
import com.zsvg.vboot.config.security.pojo.Zmeta;
import com.zsvg.vboot.config.security.pojo.Zuser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.security.core.Authentication;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import javax.websocket.server.PathParam;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
public class AuthnController {
@PostMapping("/login")
public RestResult login(@Valid @RequestBody LoginDto loginDTO) throws IOException, ClassNotFoundException {
System.out.println("开始登录");
//1.登录验证
Duser duser = null;
try {
duser = jdbcDao.getTp().queryForObject("select id,name,pacod,retag from sys_org_user where usnam=? and avtag=1",
new Object[]{loginDTO.getUsername()}, new BeanPropertyRowMapper<>(Duser.class));
} catch (DataAccessException ignored) {
}
boolean passFlag = false;
if (duser != null) {
String encodePassword = DigestUtils.md5DigestAsHex(("abc" + loginDTO.getPassword() + "xyz").getBytes());//数据库密码验证
if (encodePassword.equals(duser.getPacod())) {
passFlag = true;
} else {
passFlag = ldapService.authenticate(loginDTO.getUsername(), loginDTO.getPassword());//AD域密码验证
}
}
if (!passFlag) {
return RestResult.build(402, "账号不存在或密码错误");
}
//2.初始化用户信息,获取菜单与权限
String atokenUUID = IdUtil.simpleUUID();
String atoken = jwtHandler.createTokenByUuid(atokenUUID);
String rtoken = jwtHandler.createTokenByUuid(loginDTO.getUsername());//需要加密下
Map<String, Object> backMap = new HashMap<>();
backMap.put("token", atoken);
backMap.put("rtoken", rtoken);
Zuser zuser = new Zuser(duser.getId(), duser.getName(), loginDTO.getUsername());
authnService.initZuser(zuser, duser, backMap);//初始化用户
redisHandler.set(atokenUUID, zuser, appConfig.getJwt().getAtime());//默认8小时过期
//3.登录日志记录
return RestResult.ok(backMap);
}
@GetMapping("/rtoken")
public RestResult rtoken(@PathParam("token2") String token2) {
System.out.println("token2=" + token2);
String username = jwtHandler.getClaims(token2).getId();
System.out.println("username=" + username);
String uuid = IdUtil.simpleUUID();
String token = jwtHandler.createTokenByUuid(uuid);
Zuser zuser = authnService.getUser(username);
redisHandler.set(uuid, zuser, 10000 / 1000);
Map<String, Object> backMap = new HashMap<>();
backMap.put("token", token);
return RestResult.ok(backMap);
}
@GetMapping("/getMenuList")
public RestResult getMenuList(Authentication auth) {
List<Zmenu> zmenuList = new ArrayList<>();
Zmenu zmenu = new Zmenu();
zmenu.setPath("/sys/org");
zmenu.setName("SysOrg");
zmenu.setComponent("LAYOUT");
zmenu.setRedirect("/sys/org/user");
Zmeta zmeta = new Zmeta();
zmeta.setOrderNo(1);
zmeta.setIcon("ant-design:apartment-outlined");
zmeta.setTitle("组织架构");
zmenu.setMeta(zmeta);
zmenuList.add(zmenu);
Zmenu zmenu2 = new Zmenu();
zmenu2.setPath("dept");
zmenu2.setName("SysOrgDept");
zmenu2.setComponent("/sys/org/dept/index.vue");
Zmeta zmeta2 = new Zmeta();
zmeta2.setOrderNo(1);
zmeta2.setIcon("ant-design:apartment-outlined");
zmeta2.setTitle("部门管理");
zmeta2.setIgnoreKeepAlive(false);
zmenu2.setMeta(zmeta2);
zmenu.setChildren(new ArrayList<>());
zmenu.getChildren().add(zmenu2);
// return RestResult.ok(authnService.findMenuList(auth));
return RestResult.ok(zmenuList);
}
@Autowired
private AuthnService authnService;
@Autowired
private AppConfig appConfig;
@Autowired
private RedisHandler redisHandler;
@Autowired
private JwtHandler jwtHandler;
@Autowired
private LdapService ldapService;
@Autowired
private JdbcDao jdbcDao;
@Autowired
private SysOrgUserService userService;
}
@@ -0,0 +1,40 @@
package com.zsvg.vboot.config.security.authn;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Component
public class AuthnFailedHandler implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
if (!response.isCommitted()) {
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setStatus(200);
response.setHeader("Content-Type", "application/json;charset=UTF-8");
try (ServletOutputStream ous = response.getOutputStream()) {
Map<String, Object> map = new HashMap<>(16);
map.put("code", HttpStatus.SC_UNAUTHORIZED);
// map.put("code", HttpStatus.SC_OK);
map.put("success", false);
System.out.println(e.getMessage());
// response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
map.put("message", Optional.ofNullable(request.getAttribute("errorMessage")).orElse("认证失败").toString());
ous.write(JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8));
}
}
}
}
@@ -0,0 +1,262 @@
package com.zsvg.vboot.config.security.authn;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.zsvg.vboot.common.mvc.dao.JdbcDao;
import com.zsvg.vboot.config.security.pojo.Duser;
import com.zsvg.vboot.config.security.pojo.Zmenu;
import com.zsvg.vboot.config.security.pojo.Zmeta;
import com.zsvg.vboot.config.security.pojo.Zuser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Service
@Transactional(rollbackFor = Exception.class)
public class AuthnService {
public void initZuser(Zuser zuser, Duser duser, Map<String, Object> backMap) {
if (!duser.getRetag()) {
//1.获取用户所有的组织架构集:conds
String conds = findConds(duser);
zuser.setConds(conds);
//2.根据组织架构集conds查询前台菜单集:menus
List<Zmenu> menuList = findMenuList(zuser.getConds());
//3.根据组织架构集conds查询前台按钮集:btns
List<String> btnList = findBtnList(zuser.getConds());
//4.计算后台缓存的url权限集
List<String> permList = new ArrayList<>();
for (Zmenu menu : menuList) {
if (StrUtil.isNotBlank(menu.getPerm())) {
permList.add(menu.getPerm());
}
}
permList.addAll(btnList);
zuser.setPermList(permList);
//5.设置前台返回数据
menuList = buildTree(menuList);
backMap.put("menus", menuList);
backMap.put("btns", btnList);
backMap.put("zuser", zuser);
//6.更新用户,序列化保存数据,使下次这些数据可直接从数据库取
updateUser(zuser, menuList, btnList);
System.out.println("通过数据库");
} else {
String sql = "select conds,menus,btns,perms from sys_org_user where id=?";
Map<String, Object> map = jdbcDao.findMap(sql, zuser.getId());
zuser.setConds((String) map.get("conds"));
List<Zmenu> menuList = JSON.parseArray((String) map.get("menus"), Zmenu.class);
String[] btnArr = null;
String btns = (String) map.get("btns");
if (btns != null) {
btnArr = btns.split(";");
}
String[] permArr = null;
String perms = (String) map.get("perms");
if (perms != null) {
permArr = perms.split(";");
}
List<String> permList = new ArrayList<>();
if (permArr != null) {
permList = Arrays.asList(permArr);
}
zuser.setPermList(permList);
backMap.put("menus", menuList);
backMap.put("btns", btnArr);
backMap.put("zuser", zuser);
System.out.println("通过缓存");
}
// //初始化数据库user
// String perms = "";
// for (int i = 0; i < permSum.length; i++) {
// perms += permSum[i] + ";";
// }
// if (!perms.equals("")) {
// perms = perms.substring(0, perms.length() - 1);
// } else {
// perms = "0";
// }
// updatePerson(perms, conds, id);
// zuser = new Zuser(id, "" + orgInfo.get("name"), sysOrgUser.getUsnam(), permSum, conds);
// zuser.setAdmin(XuserUtil.isAdmin(sysOrgUser.getUsnam()));
// zuser.setWatag(sysOrgUser.getWatag());
// } else {
// String[] permArr = sysOrgUser.getPerms().split(";");
// long[] permSum = new long[permArr.length];
// for (int i = 0; i < permArr.length; i++) {
// permSum[i] = Long.parseLong(permArr[i]);
// }
// zuser = new Zuser(id, "" + orgInfo.get("name"), "" + sysOrgUser.getUsnam(), permSum, sysOrgUser.getConds());
// zuser.setAdmin(XuserUtil.isAdmin(sysOrgUser.getUsnam()));
// zuser.setWatag(sysOrgUser.getWatag());
// }
// return zuser;
}
// private void calcPerms(Zuser zuser,){
// //查询权限集合
// Integer posSum = SysAuthPermService.AUTHPOS + 1;//取出最大权限位
// long[] permSum = new long[posSum];
////
// List<Zperm> zpermList = getPermList(conds);
// for (Zperm zperm : zpermList) {
// for (int i = 0; i < posSum; i++) {
// if (i == zperm.getPos()) {
// permSum[i] = permSum[i] + zperm.getCode();
// }
// }
// }
// }
private String findConds(Duser duser) {
StringBuilder conds = new StringBuilder();
//1. conds拼接父级id
if (StrUtil.isNotBlank(duser.getTier())) {
String[] pidArr = duser.getTier().split("x");
for (int i = pidArr.length - 1; i >= 0; i--) {
if (!"".equals(pidArr[i])) {
conds.append("'").append(pidArr[i]).append("',");
}
}
} else {
conds = new StringBuilder("'" + duser.getId() + "',");
}
//2. conds拼接岗位id
List<String> postList = findPostList(duser.getId());
for (String str : postList) {
conds.append("'").append(str).append("',");
}
conds = new StringBuilder(conds.substring(0, conds.length() - 1));//优化
//3. conds拼接群组id
List<String> groupList = findGroupList(conds.toString());
for (String str : groupList) {
conds.append(",'").append(str).append("'");
}
return conds.toString();
}
private List<String> findPostList(String uid) {
String sql = "select pid as id from sys_org_post_user where uid=?";
return jdbcDao.findStringList(sql, uid);
}
private List<String> findGroupList(String conds) {
String sql = "select DISTINCT gid as id from sys_org_group_org where oid in (" + conds + ")";
return jdbcDao.findStringList(sql);
}
private List<Zmenu> findMenuList(String conds) {
String sql = "select distinct m.name,m.code,m.path,m.icon,m.comp,m.ornum,m.id,m.pid,m.perm from sys_auth_menu m inner join sys_auth_role_menu rm on rm.mid=m.id inner join sys_auth_role_org ru on ru.rid=rm.rid where m.type in ('D','M') and m.avtag=1 and ru.oid in (" + conds + ") order by m.ornum";
if(conds.contains("'sa'")||conds.contains("'vben'")){
sql = "select m.name,m.code,m.path,m.icon,m.comp,m.ornum,m.id,m.pid,m.perm from sys_auth_menu m where m.type in ('D','M') and m.avtag=1 order by m.ornum";
}
List<Zmenu> list = jdbcDao.getTp().query(sql, (rs, rowNum) -> {
Zmenu zmenu = new Zmenu();
zmenu.setId(rs.getString("id"));
zmenu.setPid(rs.getString("pid"));
zmenu.setPerm(rs.getString("perm"));
zmenu.setName(rs.getString("code"));
zmenu.setPath(rs.getString("path"));
zmenu.setComponent(rs.getString("comp"));
Zmeta zmeta = new Zmeta();
zmeta.setTitle(rs.getString("name"));
zmeta.setOrderNo(rs.getInt("ornum"));
zmeta.setIcon(rs.getString("icon"));
zmenu.setMeta(zmeta);
return zmenu;
});
return list;
}
//使用递归方法建树
private List<Zmenu> buildTree(List<Zmenu> treeNodes) {
List<Zmenu> trees = new ArrayList<>();
for (Zmenu treeNode : treeNodes) {
if (treeNode.getPid() == null) {
trees.add(recTree(treeNode, treeNodes));
}
}
return trees;
}
//递归查找子节点
private Zmenu recTree(Zmenu treeNode, List<Zmenu> treeNodes) {
for (Zmenu it : treeNodes) {
if (treeNode.getId().equals(it.getPid())) {
if (treeNode.getChildren() == null) {
treeNode.setChildren(new ArrayList<>());
}
treeNode.getChildren().add(recTree(it, treeNodes));
}
}
return treeNode;
}
private List<String> findBtnList(String conds) {
String sql = "select distinct m.perm id from sys_auth_menu m inner join sys_auth_role_menu rm on rm.mid=m.id inner join sys_auth_role_org ru on ru.rid=rm.rid where m.type = 'B' and m.avtag=1 and ru.oid in (" + conds + ") order by m.ornum";
if(conds.contains("'sa'")||conds.contains("'vben'")){
sql = "select m.perm id from sys_auth_menu m where m.type = 'B' and m.avtag=1 order by m.ornum";
}
return jdbcDao.findStringList(sql);
}
private void updateUser(Zuser zuser, List<Zmenu> menuList, List<String> btnList) {
String menus = JSON.toJSONString(menuList);
StringBuilder btns = new StringBuilder();
for (String str : btnList) {
btns.append(str).append(";");
}
StringBuilder perms = new StringBuilder();
for (String str : zuser.getPermList()) {
perms.append(str).append(";");
}
String sql = "update sys_org_user set conds=?,menus=?,btns=?,perms=?,retag=1 where id=?";
jdbcDao.update(sql, zuser.getConds(), menus, btns.toString(), perms.toString(), zuser.getId());
}
@Transactional(readOnly = true)
public Zuser getUser(String username) {
Map<String, Object> map = jdbcDao.getTp().queryForMap("select u.id,u.name from sys_org_user u where u.usnam=? and u.avtag=1", username);
Zuser user = new Zuser();
user.setId((String) map.get("id"));
user.setName((String) map.get("name"));
return user;
}
@Autowired
private JdbcDao jdbcDao;
}
@@ -0,0 +1,38 @@
package com.zsvg.vboot.config.security.authn;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.stereotype.Service;
import javax.naming.directory.DirContext;
@Service
public class LdapService {
@Autowired
private LdapTemplate ldapTemplate;
@Value("${ldap.domainName}")
private String ldapDomainName;
@Value("${ldap.base}")
private String ldapBaseDn;
public boolean authenticate(String userName, String password) {
//String userDomainName = getDnForUser(userName);
String userDomainName = String.format(ldapDomainName, userName);
DirContext ctx = null;
try {
ctx = ldapTemplate.getContextSource().getContext(userDomainName, password);
return true;
} catch (Exception e) {
// e.printStackTrace();
} finally {
LdapUtils.closeContext(ctx);
}
return false;
}
}
@@ -0,0 +1,22 @@
package com.zsvg.vboot.config.security.authn;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginDto implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull
private String username;
@NotNull
private String password;
}
@@ -0,0 +1,40 @@
package com.zsvg.vboot.config.security.authz;
import com.zsvg.vboot.common.mvc.api.RestResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AuthzController {
@GetMapping("/getUserInfo")
public RestResult getUserInfo(Authentication auth) {
return RestResult.ok("test");
}
@GetMapping("/getPermCode")
public RestResult getPermCode(Authentication auth) {
return RestResult.ok("test");
}
@GetMapping("/com/getZuser")
public RestResult getZuser(Authentication auth) {
return RestResult.ok("test");
}
@Autowired
private AuthzService authzService;
}
@@ -0,0 +1,36 @@
package com.zsvg.vboot.config.security.authz;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Component
public class AuthzDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
response.setStatus(403);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setHeader("Content-Type", "application/json;charset=UTF-8");
try (ServletOutputStream ous = response.getOutputStream()) {
Map<String, Object> map = new HashMap<>(16);
map.put("code", HttpStatus.SC_FORBIDDEN);
map.put("success", false);
map.put("message", Optional.ofNullable(request.getAttribute("errorMessage")).orElse("授权失败").toString());
ous.write(JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8));
}
}
}
@@ -0,0 +1,21 @@
package com.zsvg.vboot.config.security.authz;
import com.zsvg.vboot.config.security.pojo.Zuser;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class AuthzHandler {
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
String uri=request.getRequestURI();
Zuser zuser = (Zuser) authentication.getPrincipal();
return true;
}
}
@@ -0,0 +1,66 @@
package com.zsvg.vboot.config.security.authz;
import com.zsvg.vboot.common.mvc.dao.JdbcDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(rollbackFor = Exception.class)
public class AuthzService {
// public List<Zmenu> findMenuList(Authentication auth) {
// String sql = "select name,code,path,icon,comp,ornum,id,pid from sys_auth_menu where type in ('D','M') and avtag=1 order by ornum";
// List<Zmenu> list=jdbcDao.getTp().query(sql, (rs, rowNum) -> {
// Zmenu zmenu = new Zmenu();
// zmenu.setId(rs.getString("id"));
// zmenu.setPid(rs.getString("pid"));
// zmenu.setName(rs.getString("code"));
// zmenu.setPath(rs.getString("path"));
// zmenu.setComponent(rs.getString("comp"));
// Zmeta zmeta = new Zmeta();
// zmeta.setTitle(rs.getString("name"));
// zmeta.setOrderNo(rs.getInt("ornum"));
// zmeta.setIcon(rs.getString("icon"));
// zmenu.setMeta(zmeta);
// return zmenu;
// });
// return buildByRecursive(list);
// }
//
//
// //使用递归方法建树
// public List<Zmenu> buildByRecursive(List<Zmenu> treeNodes) {
// List<Zmenu> trees = new ArrayList<>();
// for (Zmenu treeNode : treeNodes) {
// if (treeNode.getPid()==null) {
// trees.add(findChildrenByTier(treeNode,treeNodes));
// }
// }
// return trees;
// }
//
//
// //递归查找子节点
// public Zmenu findChildrenByTier(Zmenu treeNode, List<Zmenu> treeNodes) {
//// treeNode.setChildren(new ArrayList<>());
// for (Zmenu it : treeNodes) {
// if(treeNode.getId().equals(it.getPid())) {
// if (treeNode.getChildren() == null) {
// treeNode.setChildren(new ArrayList<>());
// }
// treeNode.getChildren().add(findChildrenByTier(it,treeNodes));
// }
// }
// return treeNode;
// }
@Autowired
private JdbcDao jdbcDao;
}
@@ -0,0 +1,64 @@
package com.zsvg.vboot.config.security.jwt;
import com.zsvg.vboot.config.dbx.redis.RedisHandler;
import com.zsvg.vboot.config.security.pojo.Zuser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
public class JwtFilter extends OncePerRequestFilter {
private final JwtHandler jwtHandler;
private final RedisHandler redisHandler;
public JwtFilter(JwtHandler jwtHandler, RedisHandler redisHandler) {
this.jwtHandler = jwtHandler;
this.redisHandler = redisHandler;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
// System.out.println("拦截的URL:" + request.getRequestURI());
String token = jwtHandler.getToken(request);
if (token != null) {
String uuid = jwtHandler.getClaims(token).getId();
// System.out.println("过滤器:uuid:" + uuid);
Zuser zuser = (Zuser) redisHandler.get(uuid);
if (zuser != null) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(zuser, null, zuser.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
} else {
// response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "当前登录状态过期");
throw new BadCredentialsException("当前登录状态过期");
}
}
//测试用时
String uri = request.getRequestURI();
String ip = request.getRemoteAddr();
long start = System.currentTimeMillis();
log.debug(ip + "--" + uri + "--开始▼...");
chain.doFilter(request, response);
long time = (System.currentTimeMillis() - start);
if (time > 3000) {
log.warn(ip + "--" +uri + "--结束▲...用时:" + time / 1000 + "秒");
} else {
log.debug(ip + "--"+uri + "--结束▲...用时:" + time + "毫秒");
}
}
}
@@ -0,0 +1,22 @@
package com.zsvg.vboot.config.security.jwt;
import lombok.RequiredArgsConstructor;
import com.zsvg.vboot.config.dbx.redis.RedisHandler;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@RequiredArgsConstructor
public class JwtFilterAdapter extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final JwtHandler jwtHandler;
private final RedisHandler redisHandler;
@Override
public void configure(HttpSecurity http) throws Exception {
JwtFilter jwtFilter = new JwtFilter(jwtHandler, redisHandler);
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
@@ -0,0 +1,97 @@
package com.zsvg.vboot.config.security.jwt;
import cn.hutool.core.util.IdUtil;
import com.zsvg.vboot.config.AppConfig;
import com.zsvg.vboot.config.dbx.redis.RedisHandler;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.util.ArrayList;
@Component
public class JwtHandler implements InitializingBean {
private final Key key; // 用于签名 Access Token
private final Key refreshKey; // 用于签名 Refresh Token
private final AppConfig appConfig;
private JwtParser jwtParser;
private JwtBuilder jwtBuilder;
private final RedisHandler redisHandler;
public JwtHandler(AppConfig appConfig, RedisHandler redisHandler) {
this.appConfig = appConfig;
this.redisHandler = redisHandler;
key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(appConfig.getJwt().getAkey()));
refreshKey = Keys.hmacShaKeyFor(Decoders.BASE64.decode(appConfig.getJwt().getRkey()));
}
@Override
public void afterPropertiesSet() {
jwtParser = Jwts.parserBuilder().setSigningKey(key).build();
jwtBuilder = Jwts.builder().signWith(key, SignatureAlgorithm.HS512);
}
//创建Token 设置永不过期,Token 的时间有效性转到Redis 维护
public String createToken(Authentication authentication) {
return jwtBuilder
// 加入ID确保生成的 Token 都不一致
.setId(IdUtil.simpleUUID())
.claim("user", authentication.getName())
.setSubject(authentication.getName())
.compact();
}
public String createTokenByUuid(String uuid) {
// System.out.println("uuidz:" + uuid);
return jwtBuilder
.setId(uuid)
.claim("username", uuid)
.setSubject(uuid)
.compact();
}
//依据Token 获取鉴权信息
Authentication getAuthentication(String token) {
Claims claims = getClaims(token);
User principal = new User(claims.getSubject(), "******", new ArrayList<>());
return new UsernamePasswordAuthenticationToken(principal, token, new ArrayList<>());
}
public Claims getClaims(String token) {
return jwtParser
.parseClaimsJws(token)
.getBody();
}
//需要检查的token
// public void checkRenewal(String token) {
// // 判断是否续期token,计算token的过期时间
// long time = redisHandler.getExpire("online" + token) * 1000;
// Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time);
// // 判断当前时间与过期时间的时间差
// long differ = expireDate.getTime() - System.currentTimeMillis();
// // 如果在续期检查的范围内,则续期
// if (differ <= appConfig.getJwt().getDetect()) {
// long renew = time + appConfig.getJwt().getRenew();
// redisHandler.expire(appConfig.getJwt().getOnlineKey() + token, renew, TimeUnit.MILLISECONDS);
// }
// }
public String getToken(HttpServletRequest request) {
final String requestHeader = request.getHeader(appConfig.getJwt().getHeader());
if (requestHeader != null && requestHeader.startsWith(appConfig.getJwt().getPrefix())) {
return requestHeader.substring(7);
}
return null;
}
}
@@ -0,0 +1,18 @@
package com.zsvg.vboot.config.security.pojo;
import lombok.Data;
@Data
public class Duser {
private String id;
private String name;
private String pacod;
private Boolean retag;
private String tier;
}
@@ -0,0 +1,38 @@
package com.zsvg.vboot.config.security.pojo;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class Zmenu implements Serializable {
private static final long serialVersionUID = 1L;
@JsonIgnore
@JSONField(serialize = false)
private String id;
@JsonIgnore
@JSONField(serialize = false)
private String pid;
@JsonIgnore
@JSONField(serialize = false)
private String perm;
private String path;
private String name;
private String component;
private Zmeta meta;
private String redirect;
private List<Zmenu> children;
}
@@ -0,0 +1,21 @@
package com.zsvg.vboot.config.security.pojo;
import lombok.Data;
import java.io.Serializable;
@Data
public class Zmeta implements Serializable {
private static final long serialVersionUID = 1L;
private String title;
private String affix;
private String icon;
private Integer orderNo;
private Boolean ignoreKeepAlive;
}
@@ -0,0 +1,120 @@
package com.zsvg.vboot.config.security.pojo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
@Data
public class Zuser implements UserDetails, Serializable {
private static final long serialVersionUID = -2487878824333265058L;
private String id;//用户ID
private String name;//用户名称
private Boolean watag;
private String usnam;//用户名
@JsonIgnore//前端不需要
private long[] permArr;//权限集,用于验证URL权限 比较下哪个方式快1
@JsonIgnore
private List<String> permList;//权限集,用于验证URL权限 比较下哪个方式快2
@JsonIgnore//前端不需要
private String conds;//组织架构集,用户ID,所有上级部门ID,岗位ID,群组ID
public Zuser(String id, String name, String usnam, long[] perms, String conds) {
this.id = id;
this.name = name;
this.usnam = usnam;
this.conds = conds;
this.permArr = perms;
}
public Zuser() {
}
public Zuser(String id, String name, String usnam) {
this.id = id;
this.name = name;
this.usnam = usnam;
}
//------------------------------
private boolean isAdmin;
public boolean isAdmin() {
return isAdmin;
}
public void setAdmin(boolean admin) {
isAdmin = admin;
}
public boolean hasPerm(int pos, long code) {
if (isAdmin()) {
return true;
}
if (permArr.length <= pos) {
return false;
}
long ret = permArr[pos] & code;
return !(ret == 0);
}
//----------------------------UserDetails------------------------------------------------
@JsonIgnore
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@JsonIgnore
@Override
public String getPassword() {
return null;
}
@JsonIgnore
@Override
public String getUsername() {
return this.getUsnam();
}
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isEnabled() {
return true;
}
//@JSONField(serialize = false)
}
@@ -0,0 +1,24 @@
package com.zsvg.vboot.config.web;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
// .allowedHeaders("Authorization")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
.maxAge(3600);
}
};
}
}
@@ -0,0 +1,75 @@
package com.zsvg.vboot.config.web;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Value("${http.maxTotal}")
private Integer maxTotal;
@Value("${http.defaultMaxPerRoute}")
private Integer defaultMaxPerRoute;
@Value("${http.connectTimeout}")
private Integer connectTimeout;
@Value("${http.connectionRequestTimeout}")
private Integer connectionRequestTimeout;
@Value("${http.socketTimeout}")
private Integer socketTimeout;
@Value("${http.staleConnectionCheckEnabled}")
private boolean staleConnectionCheckEnabled;
@Value("${http.validateAfterInactivity}")
private Integer validateAfterInactivity;
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(httpRequestFactory());
}
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
@Bean
public HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(maxTotal); // 最大连接数
connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute); //单个路由最大连接数
connectionManager.setValidateAfterInactivity(validateAfterInactivity); // 最大空间时间
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(socketTimeout) //服务器返回数据(response)的时间,超过抛出read timeout
.setConnectTimeout(connectTimeout) //连接上服务器(握手成功)的时间,超出抛出connect timeout
.setStaleConnectionCheckEnabled(staleConnectionCheckEnabled) // 提交前检测是否可用
.setConnectionRequestTimeout(connectionRequestTimeout)//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
.build();
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
}
}
@@ -0,0 +1,19 @@
package com.zsvg.vboot.config.web;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebSocketConfig {
/**
* ServerEndpointExporter 作用
*
* 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint
*
* @return
*/
//影响单元测试所以先注释了
// @Bean
// public ServerEndpointExporter serverEndpointExporter() {
// return new ServerEndpointExporter();
// }
}
@@ -0,0 +1,92 @@
package com.zsvg.vboot.config.web;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
//影响单元测试所以先注释了
//@ServerEndpoint("/webSocket/{sid}")
@Component
public class WebSocketServer {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static AtomicInteger onlineNum = new AtomicInteger();
//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();
//发送消息
public void sendMessage(Session session, String message) throws IOException {
if(session != null){
synchronized (session) {
// System.out.println("发送数据:" + message);
session.getBasicRemote().sendText(message);
}
}
}
//给指定用户发送信息
public void sendInfo(String userName, String message){
Session session = sessionPools.get(userName);
try {
sendMessage(session, message);
}catch (Exception e){
e.printStackTrace();
}
}
//建立连接成功调用
@OnOpen
public void onOpen(Session session, @PathParam(value = "sid") String userName){
sessionPools.put(userName, session);
addOnlineCount();
System.out.println(userName + "加入webSocket!当前人数为" + onlineNum);
try {
sendMessage(session, "欢迎" + userName + "加入连接!");
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭连接时调用
@OnClose
public void onClose(@PathParam(value = "sid") String userName){
sessionPools.remove(userName);
subOnlineCount();
System.out.println(userName + "断开webSocket连接!当前人数为" + onlineNum);
}
//收到客户端信息
@OnMessage
public void onMessage(String message) throws IOException{
message = "客户端:" + message + ",已收到";
System.out.println(message);
for (Session session: sessionPools.values()) {
try {
sendMessage(session, message);
} catch(Exception e){
e.printStackTrace();
continue;
}
}
}
//错误时调用
@OnError
public void onError(Session session, Throwable throwable){
System.out.println("发生错误");
throwable.printStackTrace();
}
public static void addOnlineCount(){
onlineNum.incrementAndGet();
}
public static void subOnlineCount() {
onlineNum.decrementAndGet();
}
}
@@ -0,0 +1,15 @@
package com.zsvg.vboot.module.ass.dict.cate;
import lombok.Getter;
import lombok.Setter;
import com.zsvg.vboot.common.mvc.entity.BaseCateEntity;
import javax.persistence.Entity;
@Entity
@Getter
@Setter
public class AssDictCate extends BaseCateEntity {
private String notes;//备注
}
@@ -0,0 +1,46 @@
package com.zsvg.vboot.module.ass.dict.cate;
import com.zsvg.vboot.common.mvc.api.RestResult;
import com.zsvg.vboot.common.mvc.dao.Sqler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("ass/dict/cate")
public class AssDictCateApi {
private String table = "ass_dict_cate";
@GetMapping
public RestResult get(String name) {
Sqler sqler = new Sqler(table);
sqler.addLike("t.name", name);
sqler.addSelect("t.notes,t.ornum");
return RestResult.ok(service.findPageData(sqler));
}
@GetMapping("one/{id}")
public RestResult getOne(@PathVariable String id) {
AssDictCate cate = service.findOne(id);
return RestResult.ok(cate);
}
@PostMapping
public RestResult post(@RequestBody AssDictCate main) {
return RestResult.ok(service.insert(main));
}
@PutMapping
public RestResult put(@RequestBody AssDictCate main) {
return RestResult.ok(service.update(main));
}
@DeleteMapping("{ids}")
public RestResult delete(@PathVariable String[] ids) {
return RestResult.ok(service.delete(ids));
}
@Autowired
private AssDictCateService service;
}
@@ -0,0 +1,8 @@
package com.zsvg.vboot.module.ass.dict.cate;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AssDictCateRepo extends JpaRepository<AssDictCate,String> {
}
@@ -0,0 +1,27 @@
package com.zsvg.vboot.module.ass.dict.cate;
import com.zsvg.vboot.common.mvc.service.BaseCateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
public class AssDictCateService extends BaseCateService<AssDictCate> {
//----------bean注入------------
@Autowired
private AssDictCateRepo repo;
@PostConstruct
public void initDao() {
super.setRepo(repo);
}
}
@@ -0,0 +1,23 @@
package com.zsvg.vboot.module.ass.dict.data;
import lombok.Getter;
import lombok.Setter;
import com.zsvg.vboot.common.mvc.entity.BaseEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
@Entity
@Getter
@Setter
public class AssDictData extends BaseEntity {
private String notes;//备注
@Column(length = 32)
private String code;//编码
private Integer ornum;
}
@@ -0,0 +1,47 @@
package com.zsvg.vboot.module.ass.dict.data;
import com.zsvg.vboot.common.mvc.api.RestResult;
import com.zsvg.vboot.common.mvc.dao.Sqler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("ass/dict/data")
public class AssDictDataApi {
private String table = "ass_dict_data";
@GetMapping
public RestResult get(String name) {
Sqler sqler = new Sqler(table);
sqler.addLike("t.name", name);
sqler.addSelect("t.notes,t.ornum,t.code");
return RestResult.ok(service.findPageData(sqler));
}
@GetMapping("one/{id}")
public RestResult getOne(@PathVariable String id) {
AssDictData main = service.findOne(id);
return RestResult.ok(main);
}
@PostMapping
public RestResult post(@RequestBody AssDictData main) {
return RestResult.ok(service.insert(main));
}
@PutMapping
public RestResult put(@RequestBody AssDictData main) {
return RestResult.ok(service.update(main));
}
@DeleteMapping("{ids}")
public RestResult delete(@PathVariable String[] ids) {
return RestResult.ok(service.delete(ids));
}
@Autowired
private AssDictDataService service;
}
@@ -0,0 +1,9 @@
package com.zsvg.vboot.module.ass.dict.data;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AssDictDataRepo extends JpaRepository<AssDictData,String> {
}
@@ -0,0 +1,31 @@
package com.zsvg.vboot.module.ass.dict.data;
import com.zsvg.vboot.common.mvc.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
public class AssDictDataService extends BaseService<AssDictData> {
//----------bean注入------------
@Autowired
private AssDictDataRepo repo;
@PostConstruct
public void initDao() {
super.setRepo(repo);
}
}
@@ -0,0 +1,22 @@
package com.zsvg.vboot.module.ass.dict.main;
import lombok.Getter;
import lombok.Setter;
import com.zsvg.vboot.common.mvc.entity.BaseMainEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
@Entity
@Getter
@Setter
public class AssDictMain extends BaseMainEntity {
private String notes;
@Column(length = 32)
private String code;//编码
private Integer ornum;
}

Some files were not shown because too many files have changed in this diff Show More