Compare commits

...

66 Commits

Author SHA1 Message Date
于连琛
1830bb64ea test 2022-07-05 11:17:35 +08:00
于连琛
0dc10a669f test 2022-07-05 09:52:58 +08:00
weihongyang
8159ffc509 feat: 🔧 新增swagger配置让swagger和actuator无冲突 2022-07-04 09:54:08 +08:00
caixiang
e5def9fb33 mark 2022-07-04 08:32:21 +08:00
caixiang
4c2e20bf0d 删掉了 ,spc不需要的模块 2022-06-30 15:28:19 +08:00
caixiang
c15c0e1f1c Merge branch 'master' of http://git.picaiba.com/why/ym
 Conflicts:
	pom.xml
	ym-gateway/src/main/java/com/cnbm/config/SwaggerConfig.java
	ym-generator/src/main/java/com/cnbm/generator/build/CodeGenerator.java
2022-06-30 11:49:31 +08:00
weihongyang
e4bfce9df3 fix: 🔧 2022-06-30 08:40:59 +08:00
weihongyang
3a090fb584 feat: 添加websocket模块之后maven必要添加 2022-06-29 16:33:10 +08:00
weihongyang
e277f2a32e feat: 给websocket的请求放行 2022-06-29 16:32:20 +08:00
weihongyang
6d792317dd feat: init websocket模块 2022-06-29 16:29:25 +08:00
weihongyang
8d6cda8f90 feat: 新增maven依赖 2022-06-29 16:28:20 +08:00
weihongyang
fdf870c779 fix: 修改定时任务的log日志 2022-06-29 16:27:40 +08:00
weihongyang
4712d0300a fix: 修改redis的数据库 2022-06-29 16:27:00 +08:00
weihongyang
58c998afb0 feat: 增加定时定任务功能的xml文件 2022-06-24 16:07:31 +08:00
weihongyang
26fee6ac1c feat: 增加定时定任务模块pom配置 2022-06-24 10:27:11 +08:00
weihongyang
92a8e17f6e feat: 增加test的yaml文件 2022-06-24 10:25:36 +08:00
weihongyang
645bafc280 feat: init定时任务 2022-06-24 10:25:17 +08:00
weihongyang
1ac94e3d4c fix: 修改全局异常处理 2022-06-23 16:00:43 +08:00
weihongyang
093d6ee362 feat: sercurity的配置文件新增加LogoutHandler的实现类 在LogoutFilter之前加入jwtAuthenticationTokenFilter 2022-06-23 15:39:49 +08:00
weihongyang
aab0ea4479 fix: 修改验证码uuid参数默认是string 2022-06-23 15:31:55 +08:00
weihongyang
d3322639de fix: 修改swagger配置增加了新的组 2022-06-23 14:21:44 +08:00
weihongyang
036cc1ac25 fix: 修改登录接口实现验证码功能 2022-06-23 14:02:00 +08:00
weihongyang
6be4ac7a62 feat: 新增验证码接口 2022-06-23 13:57:30 +08:00
weihongyang
c7c397e92d feat: 新增sercurity对于验证码接口的放行 2022-06-23 13:56:43 +08:00
weihongyang
6ba316299d feat: 新增easy captcha的maven依赖 2022-06-23 13:55:43 +08:00
weihongyang
204d758fcc feat: 新增CaptchaService实现类的方法 2022-06-23 13:55:17 +08:00
weihongyang
35812df81d fix: 把redis开关配置删除 2022-06-23 13:54:49 +08:00
weihongyang
04f1bb339e feat: 新增CaptchaService实现类 2022-06-23 13:54:11 +08:00
weihongyang
42de3bd79c fix: 修改退出账号功能 2022-06-23 12:09:55 +08:00
weihongyang
3b6496773d feat: 新增账号密码在swagger有默认值 2022-06-23 11:56:20 +08:00
weihongyang
40c7df817b feat: 新增退出账号功能 2022-06-23 11:55:44 +08:00
weihongyang
681b5fbe63 feat: 新增jackson有关配置 2022-06-23 11:55:08 +08:00
weihongyang
01863b5344 feat: 新增jackson-datatype-jsr310的maven 2022-06-23 11:54:46 +08:00
weihongyang
45435f1cb4 feat: 新增sercurity的退出账号的配置 2022-06-23 11:52:54 +08:00
weihongyang
4d57b45a02 feat: 新增sercurity的LogoutSuccessHandler的实现类 2022-06-23 11:51:36 +08:00
weihongyang
47409787a4 feat: 新增sercurity的LogoutHandler的实现类 2022-06-23 11:51:19 +08:00
weihongyang
7fe617df56 fix: 修改jackson对日期的序列化支持格式 2022-06-23 09:47:51 +08:00
weihongyang
3c4cd948d4 fix: 修改jackson对日期的序列化支持格式 2022-06-22 14:03:01 +08:00
weihongyang
89bf5bf10a feat: 新增一个swagger自动生成代码的模板引擎 2022-06-22 14:02:11 +08:00
weihongyang
e01cd0f7fd feat: 新增一个swagger自动生成代码的模板引擎 2022-06-22 14:00:18 +08:00
caixiang
5d631e77c2 mark 2022-06-22 10:23:56 +08:00
weihongyang
3a30a2a34c fix: 修改sercurity的UserDetailsService的实现类 2022-06-22 09:58:10 +08:00
weihongyang
4fe4936dfd fix: 修改全局异常捕获处理类 2022-06-22 09:57:39 +08:00
weihongyang
e130377e8c feat: 新增一个登录状态异常类 2022-06-22 09:56:52 +08:00
caixiang
3b7b592a16 Merge branch 'master' of http://git.picaiba.com/why/ym
 Conflicts:
	ym-gateway/pom.xml
2022-06-22 09:14:41 +08:00
caixiang
342f843f2c mark 2022-06-22 09:14:03 +08:00
weihongyang
2bf099ee6d fix: 修改sercurity的UserDetailsService的实现类 2022-06-21 17:01:28 +08:00
weihongyang
62d1a761cc fix: 修改sercurity的config配置 2022-06-21 17:00:45 +08:00
weihongyang
7a4b82a94c fix: 修改全局异常捕获 2022-06-21 17:00:22 +08:00
weihongyang
3f8bb4f607 fix: 修改启动类 2022-06-21 17:00:02 +08:00
weihongyang
7b1365b5cd fix: 修改自动生成代码的存放路径 2022-06-21 15:52:06 +08:00
weihongyang
111473f057 fix: 修改swagger只在开发环境中启用,在生产幻境中关闭 2022-06-21 14:47:27 +08:00
weihongyang
0218a7548a fix: 修改扫码枪监听只在生产环境中启用 2022-06-21 14:46:50 +08:00
weihongyang
3b7e924478 feat: 增加生产yml文件 2022-06-21 14:46:03 +08:00
weihongyang
696e15f436 fix: 修改项目地址 2022-06-21 14:36:11 +08:00
weihongyang
a3802411d9 fix: 修改swagger依赖的bug 2022-06-21 14:35:50 +08:00
weihongyang
b98c015abc fix: 修改sercurity的放行策略 2022-06-21 14:34:34 +08:00
weihongyang
8e06463f12 fix: 修改VelocityTemplate的模板 2022-06-21 13:44:10 +08:00
weihongyang
8ae19c6c0b fix: 修改cors的config文件 2022-06-21 13:41:39 +08:00
weihongyang
22c90cf6bc feat: 新增swagger的config配置 2022-06-21 13:40:59 +08:00
weihongyang
891cc99c54 feat: 新增swagger的maven依赖 2022-06-21 13:40:35 +08:00
weihongyang
990cb5fd0c fix: 修改yml文件的redis 2022-06-21 13:39:44 +08:00
weihongyang
2902a959f3 fix: 修改请求接口的swagger注解 2022-06-21 13:39:20 +08:00
weihongyang
266ce0c6a7 fix: 修改扫码枪监听 2022-06-21 09:44:15 +08:00
weihongyang
37a7f6ae13 修改redis配置 2022-06-21 09:14:53 +08:00
weihongyang
9cdaf85171 修改redis配置 2022-06-21 09:11:59 +08:00
100 changed files with 4042 additions and 329 deletions

25
pom.xml
View File

@@ -12,8 +12,9 @@
<module>ym-admin</module>
<module>ym-generator</module>
<module>ym-gateway</module>
<module>ym-barcode</module>
<module>yum-basic</module>
<module>ym-baisc</module>
<module>ym-schedule-task</module>
<module>ym-influx</module>
</modules>
<packaging>pom</packaging>
@@ -89,6 +90,22 @@
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- influx start-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- influx end-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
@@ -197,6 +214,10 @@
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
</dependencies>
<!-- 阿里云maven仓库 -->

View File

@@ -33,6 +33,11 @@
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>${captcha.version}</version>
</dependency>
<dependency>
<groupId>com.cnbm</groupId>
<artifactId>ym-common</artifactId>

View File

@@ -1,9 +1,26 @@
package com.cnbm.admin.config;
import com.cnbm.common.utils.DateUtils;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JSR310Module;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.TimeZone;
/**
* @Author weihongyang
* @Date 2022/6/8 10:47 AM
@@ -27,4 +44,34 @@ public class CorsConfig implements WebMvcConfigurer {
// 跨域允许时间
.maxAge(3600);
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new ByteArrayHttpMessageConverter());
converters.add(new StringHttpMessageConverter());
converters.add(new ResourceHttpMessageConverter());
converters.add(new AllEncompassingFormHttpMessageConverter());
converters.add(new StringHttpMessageConverter());
converters.add(jackson2HttpMessageConverter());
}
@Bean
public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
//Long类型转String类型
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
mapper.registerModule(simpleModule);
mapper.registerModules(new JSR310Module());
//反序列化的时候如果多了其他属性,不抛出异常
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//日期格式处理
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
converter.setObjectMapper(mapper);
return converter;
}
}

View File

@@ -1,10 +1,16 @@
package com.cnbm.admin.config;
import com.cnbm.admin.filter.JwtAuthenticationTokenFilter;
import com.cnbm.admin.handler.LogoutHandlerImpl;
import com.cnbm.admin.handler.LogoutSuccessHandlerImpl;
import com.cnbm.admin.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@@ -14,6 +20,8 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
/**
* @Author weihongyang
* @Date 2022/6/8 1:51 PM
@@ -38,6 +46,16 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AccessDeniedHandler accessDeniedHandler;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private LogoutSuccessHandlerImpl logoutSuccessHandler;
@Autowired
private LogoutHandlerImpl logoutHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
@@ -48,14 +66,27 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.and()
.authorizeRequests()
// 对于登录接口 允许匿名访问
.antMatchers("/login").anonymous()
.antMatchers("/login","/doLogout","/swagger/**","/v2/**",
"/doc.html",
"/swagger-resources/**",
"/swagger-ui/**",
"/webjars/**",
"/websocket/**",
"/influx/**",
"/captcha").anonymous()
// .antMatchers("/testCors").hasAuthority("system:dept:list222")
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
.anyRequest()
.authenticated()
// 退出登录,默认为/logout这里修改接口地址为 /doLogout
.and().logout().logoutUrl("/doLogout")
.addLogoutHandler(logoutHandler)
// 设置退出登录成功处理程序退出成功后返回JSON字符串
.logoutSuccessHandler(logoutSuccessHandler);
//添加过滤器
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(jwtAuthenticationTokenFilter, LogoutFilter.class);
//配置异常处理器
http.exceptionHandling()
//配置认证失败处理器
@@ -71,4 +102,22 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public AuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
return daoAuthenticationProvider;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 加入自定义认证, 无需配置userDetailsService否则会执行默认的provider
// auth.authenticationProvider(myAuthenticationProvider());
/* auth.userDetailsService(userService)
.passwordEncoder(passwordEncoder());*/
auth.authenticationProvider(daoAuthenticationProvider());
}
}

View File

@@ -1,19 +1,27 @@
package com.cnbm.admin.controller;
import com.cnbm.admin.handler.LogoutSuccessHandlerImpl;
import com.cnbm.admin.params.LoginParam;
import com.cnbm.admin.service.CaptchaService;
import com.cnbm.admin.service.LoginService;
import com.cnbm.admin.utils.ResponseResult;
import com.cnbm.common.exception.ErrorCode;
import com.cnbm.common.validator.AssertUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author weihongyang
@@ -28,11 +36,18 @@ public class LoginController {
@Autowired
private LoginService loginService;
@RequestMapping("/hello")
@PreAuthorize("@ex.hasAuthority('sys:user:page')")
public String hello(){
log.info("hello");
return "hello";
@Autowired
private CaptchaService captchaService;
@GetMapping("/captcha")
@ApiOperation(value = "验证码", produces="application/octet-stream")
@ApiImplicitParam(paramType = "query", dataTypeClass=String.class, name = "uuid", required = true,example = "string")
public void captcha(HttpServletResponse response, String uuid)throws IOException {
//uuid不能为空
AssertUtils.isBlank(uuid, ErrorCode.IDENTIFIER_NOT_NULL);
//生成验证码
captchaService.create(response, uuid);
}
@PostMapping("/login")
@@ -40,4 +55,10 @@ public class LoginController {
public ResponseResult login(HttpServletRequest request, @RequestBody LoginParam loginParam) {
return loginService.login(request,loginParam);
}
@PostMapping("/doLogout")
@ApiOperation(value = "退出")
public void logout(){
}
}

View File

@@ -36,12 +36,12 @@ public class SysDictDataController {
@GetMapping("page")
@ApiOperation("字典数据")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = "dictLabel", value = "字典标签", paramType = "query", dataType="String"),
@ApiImplicitParam(name = "dictValue", value = "字典值", paramType = "query", dataType="String")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = "dictLabel", value = "字典标签", paramType = "query", dataTypeClass=String.class),
@ApiImplicitParam(name = "dictValue", value = "字典值", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('sys:dept:page')")
public Result<PageData<SysDictDataDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){

View File

@@ -38,12 +38,12 @@ public class SysDictTypeController {
@GetMapping("page")
@ApiOperation("字典类型")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = "dictType", value = "字典类型", paramType = "query", dataType="String"),
@ApiImplicitParam(name = "dictName", value = "字典名称", paramType = "query", dataType="String")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = "dictType", value = "字典类型", paramType = "query", dataTypeClass=String.class),
@ApiImplicitParam(name = "dictName", value = "字典名称", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('sys:dict:page')")
public Result<PageData<SysDictTypeDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){

View File

@@ -38,10 +38,10 @@ public class SysLogErrorController {
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class)
})
public Result<PageData<SysLogErrorDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
PageData<SysLogErrorDTO> page = sysLogErrorService.page(params);

View File

@@ -38,11 +38,11 @@ public class SysLogOperationController {
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = "status", value = "状态 0失败 1成功", paramType = "query", dataType="int")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = "status", value = "状态 0失败 1成功", paramType = "query", dataTypeClass=String.class)
})
public Result<PageData<SysLogOperationDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
PageData<SysLogOperationDTO> page = sysLogOperationService.page(params);

View File

@@ -60,7 +60,7 @@ public class SysMenuController {
@GetMapping("list")
@ApiOperation("列表")
@ApiImplicitParam(name = "type", value = "菜单类型 0菜单 1按钮 null全部", paramType = "query", dataType="int")
@ApiImplicitParam(name = "type", value = "菜单类型 0菜单 1按钮 null全部", paramType = "query", dataTypeClass=Integer.class)
@PreAuthorize("@ex.hasAuthority('sys:menu:list')")
public Result<List<SysMenuDTO>> list(Integer type){
List<SysMenuDTO> list = sysMenuService.getAllMenuList(type);

View File

@@ -41,11 +41,11 @@ public class SysParamsController {
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = "paramCode", value = "参数编码", paramType = "query", dataType="String")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = "paramCode", value = "参数编码", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('sys:params:page')")
public Result<PageData<SysParamsDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
@@ -105,7 +105,7 @@ public class SysParamsController {
@GetMapping("export")
@ApiOperation("导出")
@LogOperation("导出")
@ApiImplicitParam(name = "paramCode", value = "参数编码", paramType = "query", dataType="String")
@ApiImplicitParam(name = "paramCode", value = "参数编码", paramType = "query", dataTypeClass=String.class)
@PreAuthorize("@ex.hasAuthority('sys:params:export')")
public void export(@ApiIgnore @RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
List<SysParamsDTO> list = sysParamsService.list(params);

View File

@@ -45,11 +45,11 @@ public class SysRoleController {
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = "name", value = "角色名", paramType = "query", dataType="String")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = "name", value = "角色名", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('sys:role:page')")
public Result<PageData<SysRoleDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){

View File

@@ -53,13 +53,13 @@ public class SysUserController {
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = "username", value = "用户名", paramType = "query", dataType="String"),
@ApiImplicitParam(name = "gender", value = "性别", paramType = "query", dataType="String"),
@ApiImplicitParam(name = "deptId", value = "部门ID", paramType = "query", dataType="String")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = "username", value = "用户名", paramType = "query", dataTypeClass=String.class),
@ApiImplicitParam(name = "gender", value = "性别", paramType = "query", dataTypeClass=String.class),
@ApiImplicitParam(name = "deptId", value = "部门ID", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('sys:user:page')")
public Result<PageData<SysUserDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
@@ -153,7 +153,7 @@ public class SysUserController {
@GetMapping("export")
@ApiOperation("导出")
@LogOperation("导出")
@ApiImplicitParam(name = "username", value = "用户名", paramType = "query", dataType="String")
@ApiImplicitParam(name = "username", value = "用户名", paramType = "query", dataTypeClass=String.class)
@PreAuthorize("@ex.hasAuthority('sys:user:export')")
public void export(@ApiIgnore @RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
List<SysUserDTO> list = sysUserService.list(params);

View File

@@ -0,0 +1,66 @@
package com.cnbm.admin.exception;
import com.cnbm.common.exception.ErrorCode;
import com.cnbm.common.utils.MessageUtils;
/**
* @Author weihongyang
* @Date 2022/6/22 9:44 AM
* @Version 1.0
*/
public class LoginStatusException extends RuntimeException{
private static final long serialVersionUID = 1L;
private int code;
private String msg;
public LoginStatusException(int code) {
this.code = code;
this.msg = MessageUtils.getMessage(code);
}
public LoginStatusException(int code, String... params) {
this.code = code;
this.msg = MessageUtils.getMessage(code, params);
}
public LoginStatusException(int code, Throwable e) {
super(e);
this.code = code;
this.msg = MessageUtils.getMessage(code);
}
public LoginStatusException(int code, Throwable e, String... params) {
super(e);
this.code = code;
this.msg = MessageUtils.getMessage(code, params);
}
public LoginStatusException(String msg) {
super(msg);
this.code = ErrorCode.INTERNAL_SERVER_ERROR;
this.msg = msg;
}
public LoginStatusException(String msg, Throwable e) {
super(msg, e);
this.code = ErrorCode.INTERNAL_SERVER_ERROR;
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

View File

@@ -1,87 +0,0 @@
package com.cnbm.admin.exception;
import cn.hutool.core.map.MapUtil;
import com.cnbm.admin.entity.SysLogErrorEntity;
import com.cnbm.admin.service.SysLogErrorService;
import com.cnbm.common.exception.ErrorCode;
import com.cnbm.common.exception.ExceptionUtils;
import com.cnbm.common.exception.RenException;
import com.cnbm.common.utils.HttpContextUtils;
import com.cnbm.common.utils.IpUtils;
import com.cnbm.common.utils.JsonUtils;
import com.cnbm.common.utils.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @Author weihongyang
* @Date 2022/6/10 2:05 PM
* @Version 1.0
*/
//@RestControllerAdvice
//public class RenExceptionHandler {
// private static final Logger logger = LoggerFactory.getLogger(RenExceptionHandler.class);
//
// @Autowired
// private SysLogErrorService sysLogErrorService;
//
// /**
// * 处理自定义异常
// */
// @ExceptionHandler(RenException.class)
// public Result handleRenException(RenException ex){
// Result result = new Result();
// result.error(ex.getCode(), ex.getMsg());
//
// return result;
// }
//
// @ExceptionHandler(DuplicateKeyException.class)
// public Result handleDuplicateKeyException(DuplicateKeyException ex){
// Result result = new Result();
// result.error(ErrorCode.DB_RECORD_EXISTS);
//
// return result;
// }
//
// @ExceptionHandler(Exception.class)
// public Result handleException(Exception ex){
// logger.error(ex.getMessage(), ex);
//
// saveLog(ex);
//
// return new Result().error();
// }
//
// /**
// * 保存异常日志
// */
// private void saveLog(Exception ex){
// SysLogErrorEntity log = new SysLogErrorEntity();
//
// //请求相关信息
// HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
// log.setIp(IpUtils.getIpAddr(request));
// log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
// log.setRequestUri(request.getRequestURI());
// log.setRequestMethod(request.getMethod());
// Map<String, String> params = HttpContextUtils.getParameterMap(request);
// if(MapUtil.isNotEmpty(params)){
// log.setRequestParams(JsonUtils.toJsonString(params));
// }
//
// //异常信息
// log.setErrorInfo(ExceptionUtils.getErrorStackTrace(ex));
//
// //保存
// sysLogErrorService.save(log);
// }
//}

View File

@@ -0,0 +1,112 @@
package com.cnbm.admin.exception;
import com.cnbm.admin.service.SysLogErrorService;
import com.cnbm.common.exception.ErrorCode;
import com.cnbm.common.exception.RenException;
import com.cnbm.common.utils.Result;
import lombok.extern.log4j.Log4j2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @Author weihongyang
* @Date 2022/6/10 2:05 PM
* @Version 1.0
*/
@RestControllerAdvice
@Log4j2
public class YmExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(YmExceptionHandler.class);
@Autowired
private SysLogErrorService sysLogErrorService;
/**
* 处理自定义异常
*/
@ExceptionHandler(RenException.class)
public Result handleRenException(RenException ex){
Result result = new Result();
result.error(ex.getCode(), ex.getMsg());
return result;
}
@ExceptionHandler(BadCredentialsException.class)
public Result handleBadCredentialsException(BadCredentialsException ex){
Result result = new Result();
result.error("密码错误");
return result;
}
@ExceptionHandler(UsernameNotFoundException.class)
public Result handleUsernameNotFoundException(UsernameNotFoundException ex){
Result result = new Result();
result.error(ex.getMessage());
return result;
}
@ExceptionHandler(InternalAuthenticationServiceException.class)
public Result handleInternalAuthenticationServiceException(InternalAuthenticationServiceException ex){
Result result = new Result();
result.error(ex.getMessage());
return result;
}
@ExceptionHandler(LoginStatusException.class)
public Result handleLoginStatusException(LoginStatusException ex){
Result result = new Result();
result.error(ex.getMessage());
return result;
}
@ExceptionHandler(DuplicateKeyException.class)
public Result handleDuplicateKeyException(DuplicateKeyException ex){
Result result = new Result();
result.error(ErrorCode.DB_RECORD_EXISTS);
return result;
}
// @ExceptionHandler(Exception.class)
// public Result handleException(Exception ex){
// logger.error(ex.getMessage(), ex);
//
//// saveLog(ex);
//
// return new Result().error();
// }
//
// /**
// * 保存异常日志
// */
// private void saveLog(Exception ex){
// SysLogErrorEntity log = new SysLogErrorEntity();
//
// //请求相关信息
// HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
// log.setIp(IpUtils.getIpAddr(request));
// log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
// log.setRequestUri(request.getRequestURI());
// log.setRequestMethod(request.getMethod());
// Map<String, String> params = HttpContextUtils.getParameterMap(request);
// if(MapUtil.isNotEmpty(params)){
// log.setRequestParams(JsonUtils.toJsonString(params));
// }
//
// //异常信息
// log.setErrorInfo(ExceptionUtils.getErrorStackTrace(ex));
//
// //保存
// sysLogErrorService.save(log);
// }
}

View File

@@ -0,0 +1,32 @@
package com.cnbm.admin.handler;
import com.cnbm.admin.entity.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author weihongyang
* @Date 2022/6/23 11:24 AM
* @Version 1.0
*/
@Component
public class LogoutHandlerImpl implements LogoutHandler {
@Autowired
private RedisTemplate redisTemplate;
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
//获取SecurityContextHolder中的用户id
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
String userid = loginUser.getSysUserEntity().getId().toString();
//删除redis中的值
redisTemplate.delete("login:"+userid);
}
}

View File

@@ -0,0 +1,38 @@
package com.cnbm.admin.handler;
import com.cnbm.admin.entity.LoginUser;
import com.cnbm.admin.utils.ResponseResult;
import com.cnbm.admin.utils.WebUtils;
import com.cnbm.common.utils.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author weihongyang
* @Date 2022/6/23 10:44 AM
* @Version 1.0
*/
@Component
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
@Autowired
private RedisTemplate redisTemplate;
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
ResponseResult result = new ResponseResult(HttpStatus.OK.value(),"退出成功");
String json = JsonUtils.toJsonString(result);
WebUtils.renderString(response,json);
}
}

View File

@@ -17,11 +17,11 @@ import java.io.Serializable;
public class LoginParam implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "用户名", required = true)
@ApiModelProperty(value = "用户名", required = true, example = "admin")
@NotBlank(message="用户名不能为空")
private String username;
@ApiModelProperty(value = "密码" , required = true)
@ApiModelProperty(value = "密码" , required = true, example = "admin")
@NotBlank(message="密码不能为空")
private String password;

View File

@@ -1,9 +1,25 @@
package com.cnbm.admin.service;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author weihongyang
* @Date 2022/6/8 8:55 AM
* @Version 1.0
*/
public interface CaptchaService {
/**
* 图片验证码
*/
void create(HttpServletResponse response, String uuid) throws IOException;
/**
* 验证码效验
* @param uuid uuid
* @param code 验证码
* @return true成功 false失败
*/
boolean validate(String uuid, String code);
}

View File

@@ -13,4 +13,5 @@ import javax.servlet.http.HttpServletRequest;
public interface LoginService {
ResponseResult login(HttpServletRequest request, LoginParam loginParam);
}

View File

@@ -0,0 +1,77 @@
package com.cnbm.admin.service.impl;
import com.cnbm.admin.service.CaptchaService;
import com.cnbm.common.redis.RedisKeys;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* @Author weihongyang
* @Date 2022/6/23 12:29 PM
* @Version 1.0
*/
@Service
public class CaptchaServiceImpl implements CaptchaService {
@Autowired
private RedisTemplate redisTemplate;
/**
* Local Cache 5分钟过期
*/
Cache<String, String> localCache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(5, TimeUnit.MINUTES).build();
@Override
public void create(HttpServletResponse response, String uuid) throws IOException {
response.setContentType("image/gif");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//生成验证码
SpecCaptcha captcha = new SpecCaptcha(150, 40);
captcha.setLen(5);
captcha.setCharType(Captcha.TYPE_DEFAULT);
captcha.out(response.getOutputStream());
//保存到缓存
setCache(uuid, captcha.text());
}
@Override
public boolean validate(String uuid, String code) {
//获取验证码
String captcha = getCache(uuid);
//效验成功
if(code.equalsIgnoreCase(captcha)){
return true;
}
return false;
}
private void setCache(String key, String value){
key = RedisKeys.getCaptchaKey(key);
redisTemplate.opsForValue().set(key, value, 300,TimeUnit.SECONDS);
}
private String getCache(String key){
key = RedisKeys.getCaptchaKey(key);
String captcha = (String)redisTemplate.opsForValue().get(key);
//删除验证码
if(captcha != null){
redisTemplate.delete(key);
}
return captcha;
}
}

View File

@@ -2,14 +2,17 @@ package com.cnbm.admin.service.impl;
import com.cnbm.admin.entity.LoginUser;
import com.cnbm.admin.params.LoginParam;
import com.cnbm.admin.service.CaptchaService;
import com.cnbm.admin.utils.JwtUtil;
import com.cnbm.admin.service.LoginService;
import com.cnbm.admin.utils.ResponseResult;
import com.cnbm.common.exception.ErrorCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
@@ -31,8 +34,16 @@ public class LoginServiceImpl implements LoginService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private CaptchaService captchaService;
@Override
public ResponseResult login(HttpServletRequest request, LoginParam loginParam) {
//验证码是否正确
boolean flag = captchaService.validate(loginParam.getUuid(), loginParam.getCaptcha());
if(!flag){
return new ResponseResult(ErrorCode.CAPTCHA_ERROR,"验证码错误");
}
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginParam.getUsername(),loginParam.getPassword());
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
if (Objects.isNull(authenticate)) {
@@ -48,4 +59,5 @@ public class LoginServiceImpl implements LoginService {
redisTemplate.opsForValue().set("login:"+userid,loginUser);
return new ResponseResult(200,"登录成功",map);
}
}

View File

@@ -7,10 +7,12 @@ import com.cnbm.admin.dto.SysUserDTO;
import com.cnbm.admin.entity.LoginUser;
import com.cnbm.admin.entity.SysMenuEntity;
import com.cnbm.admin.entity.SysUserEntity;
import com.cnbm.admin.exception.LoginStatusException;
import com.cnbm.admin.service.SysMenuService;
import com.cnbm.common.utils.ConvertUtils;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -46,6 +48,9 @@ public class UserDetailsServiceImpl implements UserDetailsService {
if (Objects.isNull(sysUserEntity)) {
throw new UsernameNotFoundException("用户名不存在");
}
if (sysUserEntity.getStatus() == 0) {
throw new LoginStatusException("该账户已被禁用,请联系管理员");
}
log.info("sysUserEntity的值是"+sysUserEntity.toString());
log.info("sysUserEntity.getSuperAdmin()=="+sysUserEntity.getSuperAdmin());
Set<String> userPermissions = sysMenuService.getUserPermissions(sysUserEntity);

View File

@@ -9,7 +9,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yum-basic</artifactId>
<artifactId>ym-baisc</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
@@ -18,12 +18,17 @@
<dependencies>
<dependency>
<groupId>com.cnbm</groupId>
<artifactId>ym-common</artifactId>
<artifactId>ym-admin</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.cnbm</groupId>-->
<!-- <artifactId>ym-gateway</artifactId>-->
<!-- <version>1.0-SNAPSHOT</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.cnbm</groupId>
<artifactId>ym-admin</artifactId>
<artifactId>ym-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

View File

@@ -1,9 +1,6 @@
package com.cnbm.basic.controller;
import com.cnbm.admin.annotation.LogOperation;
import com.cnbm.basic.dto.ProductTypeDTO;
import com.cnbm.basic.excel.ProductTypeExcel;
import com.cnbm.basic.service.IProductTypeService;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.page.PageData;
import com.cnbm.common.utils.ExcelUtils;
@@ -13,13 +10,14 @@ import com.cnbm.common.validator.ValidatorUtils;
import com.cnbm.common.validator.group.AddGroup;
import com.cnbm.common.validator.group.DefaultGroup;
import com.cnbm.common.validator.group.UpdateGroup;
import com.cnbm.basic.dto.ProductTypeDTO;
import com.cnbm.basic.excel.ProductTypeExcel;
import com.cnbm.basic.service.IProductTypeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
@@ -33,10 +31,10 @@ import java.util.Map;
* 产品类型 前端控制器
*
* @author why
* @since 2022-06-21
* @since 2022-06-30
*/
@RestController
@RequestMapping("/generator/productType")
@RequestMapping("/code/productType")
@Api(tags="产品类型 表")
public class ProductTypeController {
@Autowired
@@ -45,12 +43,12 @@ public class ProductTypeController {
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('generator:productType:page')")
// @PreAuthorize("@ex.hasAuthority('code:productType:page')")
public Result<PageData<ProductTypeDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
PageData<ProductTypeDTO> page = productTypeService.page(params);
@@ -59,7 +57,7 @@ public class ProductTypeController {
@GetMapping("{id}")
@ApiOperation("信息")
@PreAuthorize("@ex.hasAuthority('generator:productType:info')")
// @PreAuthorize("@ex.hasAuthority('code:productType:info')")
public Result<ProductTypeDTO> get(@PathVariable("id") Long id){
ProductTypeDTO data = productTypeService.get(id);
@@ -69,7 +67,7 @@ public class ProductTypeController {
@PostMapping
@ApiOperation("保存")
@LogOperation("保存")
@PreAuthorize("@ex.hasAuthority('generator:productType:save')")
// @PreAuthorize("@ex.hasAuthority('code:productType:save')")
public Result save(@RequestBody ProductTypeDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
@@ -82,7 +80,7 @@ public class ProductTypeController {
@PutMapping
@ApiOperation("修改")
@LogOperation("修改")
@PreAuthorize("@ex.hasAuthority('generator:productType:update')")
// @PreAuthorize("@ex.hasAuthority('code:productType:update')")
public Result update(@RequestBody ProductTypeDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
@@ -95,7 +93,7 @@ public class ProductTypeController {
@DeleteMapping
@ApiOperation("删除")
@LogOperation("删除")
@PreAuthorize("@ex.hasAuthority('generator:productType:delete')")
// @PreAuthorize("@ex.hasAuthority('code:productType:delete')")
public Result delete(@RequestBody Long[] ids){
//效验数据
AssertUtils.isArrayEmpty(ids, "id");
@@ -108,7 +106,7 @@ public class ProductTypeController {
@GetMapping("export")
@ApiOperation("导出")
@LogOperation("导出")
@PreAuthorize("@ex.hasAuthority('generator:productType:export')")
// @PreAuthorize("@ex.hasAuthority('code:productType:export')")
public void export(@ApiIgnore @RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
List<ProductTypeDTO> list = productTypeService.list(params);

View File

@@ -0,0 +1,116 @@
package com.cnbm.basic.controller;
import com.cnbm.admin.annotation.LogOperation;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.page.PageData;
import com.cnbm.common.utils.ExcelUtils;
import com.cnbm.common.utils.Result;
import com.cnbm.common.validator.AssertUtils;
import com.cnbm.common.validator.ValidatorUtils;
import com.cnbm.common.validator.group.AddGroup;
import com.cnbm.common.validator.group.DefaultGroup;
import com.cnbm.common.validator.group.UpdateGroup;
import com.cnbm.basic.dto.UnitDTO;
import com.cnbm.basic.excel.UnitExcel;
import com.cnbm.basic.service.IUnitService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* 单位 表 前端控制器
*
* @author why
* @since 2022-06-30
*/
@RestController
@RequestMapping("/code/unit")
@Api(tags="单位 表")
public class UnitController {
@Autowired
private IUnitService unitService;
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('code:unit:page')")
public Result<PageData<UnitDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
PageData<UnitDTO> page = unitService.page(params);
return new Result<PageData<UnitDTO>>().ok(page);
}
@GetMapping("{id}")
@ApiOperation("信息")
@PreAuthorize("@ex.hasAuthority('code:unit:info')")
public Result<UnitDTO> get(@PathVariable("id") Long id){
UnitDTO data = unitService.get(id);
return new Result<UnitDTO>().ok(data);
}
@PostMapping
@ApiOperation("保存")
@LogOperation("保存")
@PreAuthorize("@ex.hasAuthority('code:unit:save')")
public Result save(@RequestBody UnitDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
unitService.save(dto);
return new Result();
}
@PutMapping
@ApiOperation("修改")
@LogOperation("修改")
@PreAuthorize("@ex.hasAuthority('code:unit:update')")
public Result update(@RequestBody UnitDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
unitService.update(dto);
return new Result();
}
@DeleteMapping
@ApiOperation("删除")
@LogOperation("删除")
@PreAuthorize("@ex.hasAuthority('code:unit:delete')")
public Result delete(@RequestBody Long[] ids){
//效验数据
AssertUtils.isArrayEmpty(ids, "id");
unitService.delete(ids);
return new Result();
}
@GetMapping("export")
@ApiOperation("导出")
@LogOperation("导出")
@PreAuthorize("@ex.hasAuthority('code:unit:export')")
public void export(@ApiIgnore @RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
List<UnitDTO> list = unitService.list(params);
ExcelUtils.exportExcelToTarget(response, null, list, UnitExcel.class);
}
}

View File

@@ -13,7 +13,7 @@ import java.time.LocalDateTime;
* 产品类型
*
* @author why
* @since 2022-06-21
* @since 2022-06-30
*/
@Data
@ApiModel(value = "产品类型 表DTO对象")

View File

@@ -0,0 +1,67 @@
package com.cnbm.basic.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 单位 表
*
* @author why
* @since 2022-06-30
*/
@Data
@ApiModel(value = "单位 表DTO对象")
public class UnitDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "ID")
private BigDecimal id;
@ApiModelProperty(value = "单位 名")
private String name;
@ApiModelProperty(value = "单位 编码")
private String code;
@ApiModelProperty(value = "单位类型1 可计数2 不可计数")
private BigDecimal type;
@ApiModelProperty(value = "1 可用0 不可用")
private BigDecimal status;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "删除标志,是否有效:1 可用 0不可用")
private BigDecimal valid;
@ApiModelProperty(value = "创建人")
private BigDecimal creatorId;
@ApiModelProperty(value = "创建人姓名")
private String creatorName;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
@ApiModelProperty(value = "更新人")
private BigDecimal updaterId;
@ApiModelProperty(value = "更新人姓名")
private String updaterName;
@ApiModelProperty(value = "更新时间")
private LocalDateTime updateTime;
@ApiModelProperty(value = "版本号")
private BigDecimal version;
}

View File

@@ -15,7 +15,7 @@ import java.time.LocalDateTime;
* </p>
*
* @author why
* @since 2022-06-21
* @since 2022-06-30
*/
@Data
@TableName("product_type")
@@ -34,7 +34,7 @@ public class ProductType implements Serializable {
private String code;
@ApiModelProperty("描述")
private String desc;
private String descs;
@ApiModelProperty("1 可用0 不可用")
private BigDecimal status;

View File

@@ -0,0 +1,68 @@
package com.cnbm.basic.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* <p>
* 单位 表
* </p>
*
* @author why
* @since 2022-06-30
*/
@Data
@ApiModel(value = "Unit对象", description = "单位 表")
public class Unit implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("ID")
private BigDecimal id;
@ApiModelProperty("单位 名")
private String name;
@ApiModelProperty("单位 编码")
private String code;
@ApiModelProperty("单位类型1 可计数2 不可计数")
private BigDecimal type;
@ApiModelProperty("1 可用0 不可用")
private BigDecimal status;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("删除标志,是否有效:1 可用 0不可用")
private BigDecimal valid;
@ApiModelProperty("创建人")
private BigDecimal creatorId;
@ApiModelProperty("创建人姓名")
private String creatorName;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新人")
private BigDecimal updaterId;
@ApiModelProperty("更新人姓名")
private String updaterName;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("版本号")
private BigDecimal version;
}

View File

@@ -10,7 +10,7 @@ import java.time.LocalDateTime;
* 产品类型
*
* @author why
* @since 2022-06-21
* @since 2022-06-30
*/
@Data
public class ProductTypeExcel {

View File

@@ -0,0 +1,46 @@
package com.cnbm.basic.excel;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 单位 表
*
* @author why
* @since 2022-06-30
*/
@Data
public class UnitExcel {
@Excel(name = "ID")
private BigDecimal id;
@Excel(name = "单位 名")
private String name;
@Excel(name = "单位 编码")
private String code;
@Excel(name = "单位类型1 可计数2 不可计数")
private BigDecimal type;
@Excel(name = "1 可用0 不可用")
private BigDecimal status;
@Excel(name = "备注")
private String remark;
@Excel(name = "删除标志,是否有效:1 可用 0不可用")
private BigDecimal valid;
@Excel(name = "创建人")
private BigDecimal creatorId;
@Excel(name = "创建人姓名")
private String creatorName;
@Excel(name = "创建时间")
private LocalDateTime createTime;
@Excel(name = "更新人")
private BigDecimal updaterId;
@Excel(name = "更新人姓名")
private String updaterName;
@Excel(name = "更新时间")
private LocalDateTime updateTime;
@Excel(name = "版本号")
private BigDecimal version;
}

View File

@@ -0,0 +1,21 @@
package com.cnbm.basic.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cnbm.basic.dto.ProductTypeDTO;
import com.cnbm.common.dao.BaseDao;
import com.cnbm.basic.entity.ProductType;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Map;
/**
* 产品类型 表
*
* @author why
* @since 2022-06-30
*/
@Mapper
public interface ProductTypeMapper extends BaseDao<ProductType> {
IPage<ProductTypeDTO> page(IPage<ProductType> objectPage, @Param("param") Map<String, Object> params);
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cnbm.generator.code.mapper.ProductTypeMapper">
</mapper>

View File

@@ -1,17 +1,16 @@
package com.cnbm.basic.mapper;
import com.cnbm.basic.entity.ProductType;
import com.cnbm.common.dao.BaseDao;
import com.cnbm.basic.entity.Unit;
import org.apache.ibatis.annotations.Mapper;
/**
* 产品类型
* 单位
*
* @author why
* @since 2022-06-21
* @since 2022-06-30
*/
@Mapper
public interface ProductTypeMapper extends BaseDao<ProductType> {
public interface UnitMapper extends BaseDao<Unit> {
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cnbm.generator.mapper.ProductTypeMapper">
<mapper namespace="com.cnbm.generator.code.mapper.UnitMapper">
</mapper>

View File

@@ -1,16 +1,18 @@
package com.cnbm.basic.service;
import com.cnbm.common.page.PageData;
import com.cnbm.common.service.CrudService;
import com.cnbm.basic.dto.ProductTypeDTO;
import com.cnbm.basic.entity.ProductType;
import com.cnbm.common.service.CrudService;
import java.util.Map;
/**
* 产品类型
*
* @author why
* @since 2022-06-21
* @since 2022-06-30
*/
public interface IProductTypeService extends CrudService<ProductType, ProductTypeDTO> {
PageData<ProductTypeDTO> page (Map<String, Object> params);
}

View File

@@ -0,0 +1,15 @@
package com.cnbm.basic.service;
import com.cnbm.common.service.CrudService;
import com.cnbm.basic.dto.UnitDTO;
import com.cnbm.basic.entity.Unit;
/**
* 单位 表
*
* @author why
* @since 2022-06-30
*/
public interface IUnitService extends CrudService<Unit, UnitDTO> {
}

View File

@@ -1,13 +1,17 @@
package com.cnbm.basic.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.page.PageData;
import com.cnbm.common.service.impl.CrudServiceImpl;
import com.cnbm.basic.dto.ProductTypeDTO;
import com.cnbm.basic.entity.ProductType;
import com.cnbm.basic.mapper.ProductTypeMapper;
import com.cnbm.basic.service.IProductTypeService;
import com.cnbm.common.service.impl.CrudServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@@ -16,11 +20,15 @@ import java.util.Map;
* 产品类型
*
* @author why
* @since 2022-06-21
* @since 2022-06-30
*/
@Service
public class ProductTypeServiceImpl extends CrudServiceImpl<ProductTypeMapper, ProductType, ProductTypeDTO> implements IProductTypeService {
@Autowired
private ProductTypeMapper productTypeMapper;
@Override
public QueryWrapper<ProductType> getWrapper(Map<String, Object> params){
String id = (String)params.get("id");
@@ -31,5 +39,12 @@ public class ProductTypeServiceImpl extends CrudServiceImpl<ProductTypeMapper, P
return wrapper;
}
@Override
public PageData<ProductTypeDTO> page (Map<String, Object> params){
QueryWrapper<ProductTypeDTO> wrapper = new QueryWrapper<>();
wrapper.eq("id",params.get("id"));
IPage<ProductTypeDTO> page = productTypeMapper.page(getPage(params, Constant.CREATE_DATE, false), params);
return getPageData(page,ProductTypeDTO.class);
}
}

View File

@@ -0,0 +1,34 @@
package com.cnbm.basic.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cnbm.common.service.impl.CrudServiceImpl;
import com.cnbm.basic.dto.UnitDTO;
import com.cnbm.basic.entity.Unit;
import com.cnbm.basic.mapper.UnitMapper;
import com.cnbm.basic.service.IUnitService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 单位 表
*
* @author why
* @since 2022-06-30
*/
@Service
public class UnitServiceImpl extends CrudServiceImpl<UnitMapper, Unit, UnitDTO> implements IUnitService {
@Override
public QueryWrapper<Unit> getWrapper(Map<String, Object> params){
String id = (String)params.get("id");
QueryWrapper<Unit> wrapper = new QueryWrapper<>();
wrapper.eq(StringUtils.isNotBlank(id), "id", id);
return wrapper;
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cnbm.basic.mapper.ProductTypeMapper">
<select id="page" resultType="com.cnbm.basic.dto.ProductTypeDTO">
select *
from product_type
<where>
id = #{id)}
</where>
</select>
</mapper>

View File

@@ -1,27 +0,0 @@
<?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>ym-pass</artifactId>
<groupId>com.cnbm</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ym-barcode</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.github.kwhat</groupId>
<artifactId>jnativehook</artifactId>
<version>2.2.2</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,96 +0,0 @@
package com.cnbm.barcode.listener;
import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.NativeHookException;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @Author weihongyang
* @Date 2022/6/20 4:08 PM
* @Version 1.0
*/
@Log4j2
@Component
public class GlobalKeyListenerExample implements NativeKeyListener {
static {
try {
GlobalScreen.registerNativeHook();
} catch (NativeHookException e) {
throw new RuntimeException(e);
}
GlobalScreen.addNativeKeyListener(new GlobalKeyListenerExample());
}
protected final static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue();
public void nativeKeyPressed(NativeKeyEvent e) {
log.info("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
try {
queue.put(e.getKeyCode());
} catch (InterruptedException ex) {
ex.printStackTrace();
}
log.info("queue的数据是"+queue.toString());
int[] hotKeyArray1 = {NativeKeyEvent.VC_X, NativeKeyEvent.VC_Y,NativeKeyEvent.VC_Z};
if (5 <= queue.size() && queue.size()<= 6 && e.getKeyCode() == NativeKeyEvent.VC_ENTER && judgeCombinationKey(hotKeyArray1)){
String result = "";
List<String> collect = queue.stream().map(n -> {
return NativeKeyEvent.getKeyText(n);
}).collect(Collectors.toList());
for (String s : collect) {
result = result + s;
}
if (queue.size() == 5) {
log.info("符合标准的扫码是:"+ result.replace("Enter",""));
}else {
log.info("符合标准的扫码是:"+ result.substring(1).replace("Enter",""));
}
queue.clear();
}
if (queue.size() == 6){
queue.poll();
}
if (e.getKeyCode() == NativeKeyEvent.VC_ESCAPE) {
try {
GlobalScreen.unregisterNativeHook();
} catch (NativeHookException nativeHookException) {
nativeHookException.printStackTrace();
}
}
}
protected Boolean judgeCombinationKey(int[] hotKeyArray){
Object[] queueKey = queue.toArray();
Predicate<int[]> keyArrayPredicateOne = hotKeies -> (int)queueKey[0] == hotKeies[0]
&& (int)queueKey[1] == hotKeies[1]
&& (int)queueKey[2] == hotKeies[2];
Predicate<int[]> keyArrayPredicateTwo = hotKeies -> (int)queueKey[1] == hotKeies[0]
&& (int)queueKey[2] == hotKeies[1]
&& (int)queueKey[3] == hotKeies[2];
return queue.size() == 3 ? keyArrayPredicateOne.test(hotKeyArray) :
keyArrayPredicateOne.or(keyArrayPredicateTwo).test(hotKeyArray);
}
public void nativeKeyReleased(NativeKeyEvent e) {
log.info("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyTyped(NativeKeyEvent e) {
log.info("Key Typed: " + e.getKeyText(e.getKeyCode()));
}
}

View File

@@ -29,9 +29,50 @@
</dependency>
<dependency>
<groupId>com.cnbm</groupId>
<artifactId>ym-barcode</artifactId>
<artifactId>ym-baisc</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.cnbm</groupId>
<artifactId>ym-influx</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-actuator-autoconfigure</artifactId>-->
<!-- <version>2.7.0</version>-->
<!-- <optional>true</optional>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>com.fasterxml.jackson.core</groupId>-->
<!-- <artifactId>jackson-databind</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<dependency>
<groupId>com.cnbm</groupId>
<artifactId>ym-schedule-task</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>
</dependencies>
</project>

View File

@@ -2,6 +2,7 @@ package com.cnbm;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.oas.annotations.EnableOpenApi;
/**
* @Author weihongyang
@@ -9,9 +10,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @Version 1.0
*/
@SpringBootApplication
public class AdminApplication {
@EnableOpenApi
public class YmApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class,args);
SpringApplication.run(YmApplication.class,args);
}
}

View File

@@ -0,0 +1,186 @@
package com.cnbm.config;
import com.cnbm.common.constant.Constant;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static com.google.common.collect.Lists.newArrayList;
/**
* @Author weihongyang
* @Date 2022/6/21 10:56 AM
* @Version 1.0
*/
@Configuration
@EnableOpenApi
@Profile("dev")
@EnableWebMvc
public class SwaggerConfig {
/**
* 创建API应用
* apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现
* 本例采用指定扫描的包路径来定义指定要建立API的目录。
*
* @return
*/
@Bean
public Docket restApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("全部接口")
.apiInfo(apiInfo("Spring Boot中使用Swagger2构建RESTful APIs", "1.0"))
.useDefaultResponseMessages(true)
.forCodeGeneration(false)
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.securityContexts(Arrays.asList(securityContext()))
// ApiKey的name需与SecurityReference的reference保持一致
.securitySchemes(Arrays.asList(new ApiKey("token", "token", "header")));
}
@Bean
public Docket adminApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("admin模块接口")
.apiInfo(apiInfo("Spring Boot中使用Swagger2构建RESTful APIs", "1.0"))
.useDefaultResponseMessages(true)
.forCodeGeneration(false)
.select()
.apis(RequestHandlerSelectors.basePackage("com.cnbm.admin"))
.paths(PathSelectors.any())
.build()
.securityContexts(Arrays.asList(securityContext()))
// ApiKey的name需与SecurityReference的reference保持一致
.securitySchemes(Arrays.asList(new ApiKey("token", "token", "header")));
}
@Bean
public Docket basicApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("ym-basic")
.apiInfo(apiInfos("basic", "基础资料模块"))
.useDefaultResponseMessages(true)
.forCodeGeneration(false)
.select()
.apis(RequestHandlerSelectors.basePackage("com.cnbm.basic"))
.paths(PathSelectors.any())
.build()
.securityContexts(Arrays.asList(securityContext()))
// ApiKey的name需与SecurityReference的reference保持一致
.securitySchemes(Arrays.asList(new ApiKey("token", "token", "header")));
}
@Bean
public Docket influxApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("ym-influx")
.apiInfo(apiInfos("influx", "influx模块"))
.useDefaultResponseMessages(true)
.forCodeGeneration(false)
.select()
.apis(RequestHandlerSelectors.basePackage("com.cnbm.influx"))
.paths(PathSelectors.any())
.build()
.securityContexts(Arrays.asList(securityContext()))
// ApiKey的name需与SecurityReference的reference保持一致
.securitySchemes(Arrays.asList(new ApiKey("token", "token", "header")));
}
/**
* 创建该API的基本信息这些基本信息会展现在文档页面中
* 访问地址http://ip:port/swagger-ui.html
*
* @return
*/
private ApiInfo apiInfo(String title, String version) {
return new ApiInfoBuilder()
.title(title)
.description("ym-pass文档")
.termsOfServiceUrl("https://www.baidu.com/")
.version(version)
.build();
}
private ApiInfo apiInfos(String title, String desc) {
return new ApiInfoBuilder()
.title(title)
.description(desc)
.termsOfServiceUrl("https://www.baidu.com/")
.version("1.0")
.build();
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.build();
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope
= new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Lists.newArrayList(
new SecurityReference(Constant.TOKEN_HEADER, authorizationScopes));
}
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}

View File

@@ -37,4 +37,18 @@ spring:
# driver-class-name: org.postgresql.Driver
# url: jdbc:postgresql://123456:5432/renren_security
# username: postgres
# password: 123456
# password: 123456
influx:
url: http://192.168.0.170:8086 # URL to connect to InfluxDB.
username: caixiang # Username to use in the basic auth.
password: 251128856 # Password to use in the basic auth.
token: lkBsC27QZr1W50BSPlGxpTqNNpwuUk5uz1dZZRPSPbCG5VmNDDUo8P3UkZIhGWwfJwkuz6ZGZ7Et4_KBaG3gHw== # Token to use for the authorization.
org: qgs # Default destination organization for writes and queries.
bucket: qgs-bucket # Default destination bucket for writes.
logLevel: BODY # The log level for logging the HTTP request and HTTP response. (Default: NONE)
readTimeout: 5s # Read timeout for OkHttpClient. (Default: 10s)
writeTimeout: 5s # Write timeout for OkHttpClient. (Default: 10s)
connectTimeout: 5s # Connection timeout for OkHttpClient. (Default: 10s)
# management.health.influx.enabled=true # Whether to enable InfluxDB 2.x health check.

View File

@@ -0,0 +1,40 @@
spring:
datasource:
#MySQL
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://mysql.picaiba.com:30307/ym_pass?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
username: root
password: 1qaz@WSX3edc$RFV
# #Oracle
# driver-class-name: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@192.168.10.10:1521:xe
# username: renren_security
# password: 123456
# #SQLServer
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=renren_security
# username: sa
# password: 123456
# #postgresql
# driver-class-name: org.postgresql.Driver
# url: jdbc:postgresql://192.168.10.10:5432/postgres
# username: postgres
# password: 123456
hikari:
pool-name: GrowUpHikariCP
minimum-idle: 1
maximum-pool-size: 10
##多数据源的配置需要引用renren-dynamic-datasource
#dynamic:
# datasource:
# slave1:
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://123456:1433;DatabaseName=renren_security
# username: sa
# password: 123456
# slave2:
# driver-class-name: org.postgresql.Driver
# url: jdbc:postgresql://123456:5432/renren_security
# username: postgres
# password: 123456

View File

@@ -0,0 +1,40 @@
spring:
datasource:
#MySQL
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://mysql.picaiba.com:30307/ym_pass?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
username: root
password: 1qaz@WSX3edc$RFV
# #Oracle
# driver-class-name: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@192.168.10.10:1521:xe
# username: renren_security
# password: 123456
# #SQLServer
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=renren_security
# username: sa
# password: 123456
# #postgresql
# driver-class-name: org.postgresql.Driver
# url: jdbc:postgresql://192.168.10.10:5432/postgres
# username: postgres
# password: 123456
hikari:
pool-name: GrowUpHikariCP
minimum-idle: 1
maximum-pool-size: 10
##多数据源的配置需要引用renren-dynamic-datasource
#dynamic:
# datasource:
# slave1:
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://123456:1433;DatabaseName=renren_security
# username: sa
# password: 123456
# slave2:
# driver-class-name: org.postgresql.Driver
# url: jdbc:postgresql://123456:5432/renren_security
# username: postgres
# password: 123456

View File

@@ -7,14 +7,14 @@ server:
min-spare: 30
port: 8080
servlet:
context-path: /ym-admin
context-path: /ym-spc
session:
cookie:
http-only: true
spring:
application:
name: ym-admin
name: ym-spc
# 环境 dev|test|prod
profiles:
active: dev
@@ -24,16 +24,18 @@ spring:
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
format:
date-time: yyyy-MM-dd HH:mm:ss
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
enabled: true
redis:
database: 0
host: 124.221.241.144
port: 6379
password: why123456 # 密码(默认为空)
database: 2
host: redis.picaiba.com
port: 6380
password: '@WSXcde3' # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
jedis:
pool:
@@ -41,11 +43,10 @@ spring:
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
# 是否开启redis缓存 true开启 false关闭
renren:
redis:
open: false
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
#mybatis
mybatis-plus:
@@ -72,4 +73,5 @@ mybatis-plus:
logging:
level:
com.cnbm.admin.dao: DEBUG
com.cnbm.admin.dao: DEBUG

View File

@@ -48,8 +48,8 @@ public class CodeGenerator {
})
.packageConfig(builder -> {
//设置父包名
builder.parent("com.cnbm")
.moduleName("generator")
builder.parent("com.cnbm.generator")
.moduleName("code")
.service("service")
.serviceImpl("service.impl")
.entity("entity")

View File

@@ -3,6 +3,7 @@ package com.cnbm.generator.engine;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import com.cnbm.generator.utils.IdWorker;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -21,13 +22,19 @@ public class EnhanceVelocityTemplateEngine extends VelocityTemplateEngine {
// String otherPath = this.getPathInfo(OutputFile.other);
File file = new File("");
String path = file.getAbsolutePath();
for (int i = 0; i < 6; i++) {
objectMap.put("id"+ i, IdWorker.getId());
}
customFile.forEach((key, value) -> {
String fileName = "";
if ("DTO".equals(key)) {
fileName = String.format((path+ File.separator +"src/main/java/com/cnbm/generator"+ File.separator + "dto" + File.separator + entityName + "%s" + ".java"), key);
fileName = String.format((path+ File.separator +"src/main/java/com/cnbm/generator/code"+ File.separator + "dto" + File.separator + entityName + "%s" + ".java"), key);
}
if ("Excel".equals(key)) {
fileName = String.format((path+ File.separator +"src/main/java/com/cnbm/generator"+ File.separator + "excel" + File.separator + entityName + "%s" + ".java"), key);
fileName = String.format((path+ File.separator +"src/main/java/com/cnbm/generator/code"+ File.separator + "excel" + File.separator + entityName + "%s" + ".java"), key);
}
if ("mysql".equals(key)) {
fileName = String.format((path+ File.separator +"src/main/java/com/cnbm/generator/code"+ File.separator + "mysql" + File.separator + entityName + "%s" + ".sql"), key);
}
this.outputFile(new File(fileName), objectMap, value);
});

View File

@@ -0,0 +1,50 @@
package com.cnbm.generator.utils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
/**
* @Author weihongyang
* @Date 2022/6/22 10:52 AM
* @Version 1.0
*/
public class IdWorker {
/**
* 主机和进程的机器码
*/
private static Sequence WORKER = new Sequence();
public static long getId() {
return WORKER.nextId();
}
public static String getIdStr() {
return String.valueOf(WORKER.nextId());
}
/**
* <p>
* 有参构造器
* </p>
*
* @param workerId 工作机器 ID
* @param datacenterId 序列号
*/
public static void initSequence(long workerId, long datacenterId) {
WORKER = new Sequence(workerId, datacenterId);
}
/**
* <p>
* 使用ThreadLocalRandom获取UUID获取更优的效果 去掉"-"
* </p>
*/
public static String get32UUID() {
ThreadLocalRandom random = ThreadLocalRandom.current();
return new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY);
}
}

View File

@@ -0,0 +1,187 @@
package com.cnbm.generator.utils;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.concurrent.ThreadLocalRandom;
/**
* @Author weihongyang
* @Date 2022/6/22 10:53 AM
* @Version 1.0
*/
public class Sequence {
private static final Log logger = LogFactory.getLog(Sequence.class);
/**
* 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
*/
private final long twepoch = 1288834974657L;
/**
* 机器标识位数
*/
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
/**
* 毫秒内自增位
*/
private final long sequenceBits = 12L;
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
/**
* 时间戳左移动位
*/
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
private final long workerId;
/**
* 数据标识 ID 部分
*/
private final long datacenterId;
/**
* 并发控制
*/
private long sequence = 0L;
/**
* 上次生产 ID 时间戳
*/
private long lastTimestamp = -1L;
public Sequence() {
this.datacenterId = getDatacenterId(maxDatacenterId);
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}
/**
* <p>
* 有参构造器
* </p>
*
* @param workerId 工作机器 ID
* @param datacenterId 序列号
*/
public Sequence(long workerId, long datacenterId) {
Assert.isFalse(workerId > maxWorkerId || workerId < 0,
String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
Assert.isFalse(datacenterId > maxDatacenterId || datacenterId < 0,
String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* <p>
* 获取 maxWorkerId
* </p>
*/
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
StringBuilder mpid = new StringBuilder();
mpid.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (StringUtils.isNotEmpty(name)) {
/*
* GET jvmPid
*/
mpid.append(name.split(StringPool.AT)[0]);
}
/*
* MAC + PID 的 hashcode 获取16个低位
*/
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}
/**
* <p>
* 数据标识id部分
* </p>
*/
protected static long getDatacenterId(long maxDatacenterId) {
long id = 0L;
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
if (null != mac) {
id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
}
} catch (Exception e) {
logger.warn(" getDatacenterId: " + e.getMessage());
}
return id;
}
/**
* 获取下一个ID
*
* @return
*/
public synchronized long nextId() {
long timestamp = timeGen();
//闰秒
if (timestamp < lastTimestamp) {
long offset = lastTimestamp - timestamp;
if (offset <= 5) {
try {
wait(offset << 1);
timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
}
}
if (lastTimestamp == timestamp) {
// 相同毫秒内,序列号自增
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 同一毫秒的序列数已经达到最大
timestamp = tilNextMillis(lastTimestamp);
}
} else {
// 不同毫秒内,序列号置为 1 - 3 随机数
sequence = ThreadLocalRandom.current().nextLong(1, 3);
}
lastTimestamp = timestamp;
// 时间戳部分 | 数据中心部分 | 机器标识部分 | 序列号部分
return ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
protected long timeGen() {
return SystemClock.now();
}
}

View File

@@ -43,10 +43,10 @@ public class ${table.controllerName} {
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String")
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('${package.ModuleName}:${table.entityPath}:page')")
public Result<PageData<${entity}DTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){

View File

@@ -0,0 +1,7 @@
-- 菜单初始SQL
INSERT INTO sys_menu(id, pid, name, url, permissions, type, icon, sort, creator, create_date, updater, update_date)VALUES (${id0}, 1067246875800000035, '${table.comment}', '${package.ModuleName}/${table.entityPath}', NULL, 0, 'icon-desktop', 0, 1067246875800000001, now(), 1067246875800000001, now());
INSERT INTO sys_menu(id, pid, name, url, permissions, type, icon, sort, creator, create_date, updater, update_date) VALUES (${id1}, ${id0}, '查看', NULL, '${package.ModuleName}:${table.entityPath}:page,${package.ModuleName}:${table.entityPath}:info', 1, NULL, 0, 1067246875800000001, now(), 1067246875800000001, now());
INSERT INTO sys_menu(id, pid, name, url, permissions, type, icon, sort, creator, create_date, updater, update_date) VALUES (${id2}, ${id0}, '新增', NULL, '${package.ModuleName}:${table.entityPath}:save', 1, NULL, 1, 1067246875800000001, now(), 1067246875800000001, now());
INSERT INTO sys_menu(id, pid, name, url, permissions, type, icon, sort, creator, create_date, updater, update_date) VALUES (${id3}, ${id0}, '修改', NULL, '${package.ModuleName}:${table.entityPath}:update', 1, NULL, 2, 1067246875800000001, now(), 1067246875800000001, now());
INSERT INTO sys_menu(id, pid, name, url, permissions, type, icon, sort, creator, create_date, updater, update_date) VALUES (${id4}, ${id0}, '删除', NULL, '${package.ModuleName}:${table.entityPath}:delete', 1, NULL, 3, 1067246875800000001, now(), 1067246875800000001, now());
INSERT INTO sys_menu(id, pid, name, url, permissions, type, icon, sort, creator, create_date, updater, update_date) VALUES (${id5}, ${id0}, '导出', NULL, '${package.ModuleName}:${table.entityPath}:export', 1, NULL, 4, 1067246875800000001, now(), 1067246875800000001, now());

76
ym-influx/pom.xml Normal file
View File

@@ -0,0 +1,76 @@
<?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>ym-pass</artifactId>
<groupId>com.cnbm</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ym-influx</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-java</artifactId>
<version>6.3.0</version>
</dependency>
<!--- begin -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-test</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.hibernate.validator</groupId>-->
<!-- <artifactId>hibernate-validator</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.squareup.okhttp3</groupId>-->
<!-- <artifactId>okhttp</artifactId>-->
<!-- <version>4.9.3</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.mockito</groupId>-->
<!-- <artifactId>mockito-core</artifactId>-->
<!-- <version>4.4.0</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-actuator-autoconfigure</artifactId>-->
<!-- <version>2.7.0</version>-->
<!-- <optional>true</optional>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>com.fasterxml.jackson.core</groupId>-->
<!-- <artifactId>jackson-databind</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-configuration-processor</artifactId>-->
<!-- <version>2.7.0</version>-->
<!-- <optional>true</optional>-->
<!-- </dependency>-->
<!--- end -->
</dependencies>
</project>

View File

@@ -0,0 +1,54 @@
import com.cnbm.influx.config.InfluxClient;
import com.cnbm.influx.template.Event;
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.InfluxDBClientFactory;
import com.influxdb.client.WriteApi;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/7/1 16:39
*/
public class Main2 {
public static void main(String[] args) {
//方式1
Point point = Point.measurement("ASProcessCompleteEvent")
.addTag("transationId", "112311")
.addTag("argName", "argName11")
.addField("argValue", 3D)
.time(Instant.now().toEpochMilli(), WritePrecision.MS);
InfluxClient.Client.getWriteApi().writePoint(point);
// //方式2
// char[] token = "lkBsC27QZr1W50BSPlGxpTqNNpwuUk5uz1dZZRPSPbCG5VmNDDUo8P3UkZIhGWwfJwkuz6ZGZ7Et4_KBaG3gHw==".toCharArray();
// String org = "qgs";
// String bucket = "mytest";
// InfluxDBClient influxDBClient = InfluxDBClientFactory.create("http://192.168.0.170:8086", token, org, bucket);
// WriteApi writeApi = influxDBClient.makeWriteApi();
// Point point = Point.measurement("ASProcessCompleteEvent")
// .addTag("transationId", "112311")
// .addTag("argName", "argName11")
// .addField("argValue", 7D)
// .time(Instant.now().toEpochMilli(), WritePrecision.MS);
//
//
// Point point2 = Point.measurement("ASProcessCompleteEvent")
// .addTag("transationId", "222312")
// .addTag("argName", "argName11")
// .addField("argValue", 8D)
// .time(Instant.now().toEpochMilli(), WritePrecision.MS);
// List<Point> list = new ArrayList<>();
// list.add(point);
// list.add(point2);
// writeApi.writePoints(list);
// //一定要close 不如write 不了数据
// influxDBClient.close();
}
}

View File

@@ -0,0 +1,214 @@
package com.cnbm.influx;
import com.cnbm.influx.config.InfluxClient;
import com.cnbm.influx.param.QueryDataParam;
import com.cnbm.influx.common.Utils;
import com.cnbm.influx.param.PageInfo;
import com.cnbm.influx.param.Range;
import com.cnbm.influx.param.Tag;
import com.cnbm.influx.template.Event;
import com.influxdb.client.*;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import com.influxdb.query.FluxRecord;
import com.influxdb.query.FluxTable;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/6/25 11:19
*/
public class Main {
public static void main(String[] args) throws InterruptedException {
char[] token = "lkBsC27QZr1W50BSPlGxpTqNNpwuUk5uz1dZZRPSPbCG5VmNDDUo8P3UkZIhGWwfJwkuz6ZGZ7Et4_KBaG3gHw==".toCharArray();
String org = "qgs";
String bucket = "mytest";
InfluxDBClient influxDBClient = InfluxDBClientFactory.create("http://192.168.0.170:8086", token, org, bucket);
WriteApi writeApi = influxDBClient.makeWriteApi();
// InfluxService influxService = new InfluxService();
// Event event = new Event();
// event.time = Instant.now();
// event.transationId = "asas";
// event.argName = "arg5";
// event.argValue = new Double(11);
// influxService.insert(event);
// Event event = new Event();
// event.setTime(Instant.now());
// event.setTransationId("asasd11");
// event.setArgName("argName11");
// event.setArgValue(3d);
// InfluxClient.Client.insert(event,"ASProcessCompleteEvent");
Point point = Point.measurement("ASProcessCompleteEvent")
.addTag("transationId", "112311")
.addTag("argName", "argName11")
.addField("argValue", 3D)
.time(Instant.now().toEpochMilli(), WritePrecision.MS);
Point point2 = Point.measurement("ASProcessCompleteEvent")
.addTag("transationId", "222312")
.addTag("argName", "argName11")
.addField("argValue", 4D)
.time(Instant.now().toEpochMilli(), WritePrecision.MS);
List<Point> list = new ArrayList<>();
list.add(point);
list.add(point2);
writeApi.writePoints(list);
//todo api.writeMeasurements(WritePrecision.NS, Arrays.asList(new H2OFeetMeasurement("coyote_creek", 15.0D, null, Instant.ofEpochSecond(0, 15)), new H2OFeetMeasurement("coyote_creek", 16.0D, null, Instant.ofEpochSecond(0, 16))));
// List<Event> events = new ArrayList<>();
// for(int i=0;i<99;i++){
//
// Event event = new Event();
// event.time = Instant.now();
// event.transationId = "asas"+i;
// event.argName = "arg7";
// event.argValue = new Double(i);
// events.add(event);
// }
// List<Event> qList = new ArrayList<>();
// Event event = new Event();
// event.time = Instant.now();
// event.transationId = "asas";
// event.argName = "arg7";
// event.argValue = new Double(1);
// Thread.sleep(100);
// Event event2 = new Event();
// event2.time = Instant.now();
// event2.transationId = "asas";
// event2.argName = "arg7";
// event2.argValue = new Double(2);
// qList.add(event);
// qList.add(event2);
// writeApi.writeMeasurement( WritePrecision.NS, qList);
// for(int i=0;i<10;i++){
// Temperature temperature = new Temperature();
// temperature.location = "south";
// temperature.value = new Double(i);
// temperature.type = "equipment3";
// temperature.time = Instant.now();
//
// writeApi.writeMeasurement( WritePrecision.NS, temperature);
// }
// String flux = "from(bucket:\"mytest\") |> range(start: -60m)";
// flux += "|> filter(fn: (r) =>\n" +
// " r._measurement == \"ASProcessCompleteEvent\" and \n" +
//// " r._field == \"type\" and \n" + //对应 Field key
// " r.argName == \"arg3\"\n" + //对应 Tags key (Tag 信息无法在FluxRecord 里面获取。)
// " )";
// QueryApi queryApi = influxDBClient.getQueryApi();
//
// List<FluxTable> tables = queryApi.query(flux);
// for (FluxTable fluxTable : tables) {
// List<FluxRecord> records = fluxTable.getRecords();
// for (FluxRecord fluxRecord : records) {
// System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement());
//// System.out.println("time: "+fluxRecord.getTime() +" key:"++" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement());
//
// }
// }
// from(bucket: "mytest")
// |> range(start: 2022-06-29T11:30:00Z, stop: 2022-06-29T12:30:00Z)
// |> filter(fn: (r) => r["_measurement"] == "ASProcessCompleteEvent")
// |> filter(fn: (r) => r["argName"] == "arg4")
// |> drop(columns: ["transationId"])
// |> sort(columns: ["_time"], desc: true)
// 取前10条数据
// |> limit(n: 10, offset: 0)
// 取 10-20 条数据
// |> limit(n: 10, offset: 10)
// 取 20-30 条数据
// |> limit(n: 10, offset: 20)
// QueryDataParam queryDataParam = new QueryDataParam();
// queryDataParam.setBucket("mytest");
// queryDataParam.setRange(new Range(getDate().toInstant(),new Date().toInstant()));
// queryDataParam.setMeasurement("ASProcessCompleteEvent");
// queryDataParam.setTag(new Tag("argName","arg4"));
// queryDataParam.setDropedTagName("transationId");
// queryDataParam.setPageInfo(new PageInfo(1,100));
//
// List<FluxTable> tables = query(queryDataParam,influxDBClient);
// List<FluxRecord> records1 = tables.get(0).getRecords();
// List<List<FluxRecord>> lists = Utils.fixedGroup(records1, 10);
// for (FluxTable fluxTable : tables) {
// List<FluxRecord> records = fluxTable.getRecords();
// for (FluxRecord fluxRecord : records) {
// System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement());
//
// }
// }
influxDBClient.close();
}
public static Date getDate(){
Date date = new Date();//获取当前日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");//格式化一下
Calendar calendar1 = Calendar.getInstance();//获取对日期操作的类对象
//两种写法都可以获取到前三天的日期
// calendar1.set(Calendar.DAY_OF_YEAR,calendar1.get(Calendar.DAY_OF_YEAR) -3);
//在当前时间的基础上获取前三天的日期
calendar1.add(Calendar.DATE, -3);
//add方法 参数也可传入 月份,获取的是前几月或后几月的日期
//calendar1.add(Calendar.MONTH, -3);
Date day = calendar1.getTime();
return day;
}
private static List<FluxTable> query(QueryDataParam param,InfluxDBClient influxDBClient){
String measurement = param.getMeasurement();
String dropedTagName = param.getDropedTagName();
Range range = param.getRange();
String bucket = param.getBucket();
String tagName = param.getTag().getTagName();
String tagValue = param.getTag().getTagValue();
PageInfo pageInfo = param.getPageInfo();
String flux = "from(bucket:\""+bucket+"\")";
flux += "|> range(start: "+range.getBegin().toString()+",stop:"+range.getEnd().toString()+") \n";
flux += "|> filter(fn: (r) => r[\"_measurement\"] == \""+measurement+"\") \n";
flux += "|> filter(fn: (r) => r[\""+tagName+"\"] == \""+tagValue+"\") \n";
flux += "|> drop(columns: [\""+dropedTagName+"\"]) \n";
flux += "|> sort(columns: [\"_time\"], desc: true) \n";
if(pageInfo!=null){
flux += "|> limit(n: "+pageInfo.getSize()+", offset: "+(pageInfo.getCurrent()-1)* pageInfo.getSize()+")";
}
QueryApi queryApi = influxDBClient.getQueryApi();
List<FluxTable> tables = queryApi.query(flux);
for (FluxTable fluxTable : tables) {
List<FluxRecord> records = fluxTable.getRecords();
for (FluxRecord fluxRecord : records) {
System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement());
}
}
return tables;
}
}

View File

@@ -0,0 +1,69 @@
package com.cnbm.influx.common;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/6/29 16:23
*/
public class Utils {
public static void main(String[] args) {
ArrayList<Integer> arrs = new ArrayList<>();
for(int i=0;i<100;i++){
arrs.add(i);
}
List<List<Integer>> lists = fixedGroup(arrs, 10);
System.out.println();
}
public static Date getBeforeDate(Integer number){
Date date = new Date();//获取当前日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");//格式化一下
Calendar calendar1 = Calendar.getInstance();//获取对日期操作的类对象
//两种写法都可以获取到前三天的日期
// calendar1.set(Calendar.DAY_OF_YEAR,calendar1.get(Calendar.DAY_OF_YEAR) -3);
//在当前时间的基础上获取前三天的日期
calendar1.add(Calendar.DATE, 0-number);
//add方法 参数也可传入 月份,获取的是前几月或后几月的日期
//calendar1.add(Calendar.MONTH, -3);
Date day = calendar1.getTime();
return day;
}
/**
* 将一组数据固定分组每组n个元素
*
* @param source 要分组的数据源
* @param limit 每组n个元素
* @param <T>
* @return
*/
public static <T> List<List<T>> fixedGroup(List<T> source, int limit) {
if (null == source || source.size() == 0 || limit <= 0)
return null;
List<List<T>> result = new ArrayList<List<T>>();
int remainder = source.size() % limit;
int size = (source.size() / limit);
for (int i = 0; i < size; i++) {
List<T> subset = null;
subset = source.subList(i * limit, (i + 1) * limit);
result.add(subset);
}
if (remainder > 0) {
List<T> subset = null;
subset = source.subList(size * limit, size * limit + remainder);
result.add(subset);
}
return result;
}
}

View File

@@ -0,0 +1,133 @@
package com.cnbm.influx.config;
import com.cnbm.influx.constant.Constant;
import com.cnbm.influx.param.PageInfo;
import com.cnbm.influx.param.QueryDataParam;
import com.cnbm.influx.param.Range;
import com.cnbm.influx.template.Event;
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.InfluxDBClientFactory;
import com.influxdb.client.QueryApi;
import com.influxdb.client.WriteApi;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import com.influxdb.query.FluxTable;
import java.util.ArrayList;
import java.util.List;
public enum InfluxClient {
/**
* influxdb 读写客户端如果write比较繁忙后续可以考虑维护 client一个线程池。
* */
Client("http://192.168.0.170:8086","lkBsC27QZr1W50BSPlGxpTqNNpwuUk5uz1dZZRPSPbCG5VmNDDUo8P3UkZIhGWwfJwkuz6ZGZ7Et4_KBaG3gHw==","qgs","qgs-bucket"),
;
private String url;
private String token;
private String org;
private String bucket;
private InfluxDBClient influxDBClient;
private WriteApi writeApi;
private QueryApi queryApi;
InfluxClient(String url,String token,String org,String bucket){
this.url = url;
this.token = token;
this.org = org;
this.bucket = bucket;
this.influxDBClient = InfluxDBClientFactory.create(this.url, this.token.toCharArray(),this.org,this.bucket);
this.writeApi = influxDBClient.makeWriteApi();
this.queryApi = influxDBClient.getQueryApi();
}
public QueryApi getQueryApi() {
return queryApi;
}
public WriteApi getWriteApi() {
return writeApi;
}
/**
* 测试连接是否正常
*
* @return
* true 服务正常健康
* false 异常
*/
private boolean ping() {
boolean isConnected = false;
Boolean pong;
try {
pong = influxDBClient.ping();
if (pong != null) {
isConnected = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return isConnected;
}
public void insert(Event event, String measurement){
Point point = Point.measurement(measurement)
.addTag("transationId", event.getTransationId())
.addTag("argName", event.getArgName())
.addField("argValue", event.getArgValue())
.time(event.getTime().toEpochMilli(), WritePrecision.MS);
writeApi.writePoint(point);
}
//异步 批量写入数据
//如果要批量插入的话,一次也只能写入
public void batchInsert(List<Event> events, String measurement){
List<Point> list = new ArrayList<>();
for(Event event:events){
Point point = Point.measurement(measurement)
.addTag("transationId", event.getTransationId())
.addTag("argName", event.getArgName())
.addField("argValue", event.getArgValue())
.time(event.getTime().toEpochMilli(), WritePrecision.MS);
list.add(point);
}
writeApi.writePoints(list);
}
public List<FluxTable> query(QueryDataParam param){
String measurement = param.getMeasurement();
String dropedTagName = param.getDropedTagName();
Range range = param.getRange();
String bucket = param.getBucket();
String tagName = param.getTag().getTagName();
String tagValue = param.getTag().getTagValue();
PageInfo pageInfo = param.getPageInfo();
String flux = "from(bucket:\""+bucket+"\")";
flux += "|> range(start: "+range.getBegin()+",stop:"+range.getEnd()+")";
flux += "|> filter(fn: (r) => r[\"_measurement\"] == \""+measurement+"\")";
flux += "|> filter(fn: (r) => r[\""+tagName+"\"] == \""+tagValue+"\")";
flux += "|> drop(columns: [\""+dropedTagName+"\"])";
flux += "|> sort(columns: [\"_time\"], desc: true)";
if(pageInfo!=null){
flux += "|> limit(n: "+pageInfo.getSize()+", offset: "+(pageInfo.getCurrent()-1)* pageInfo.getSize()+")";
}
// List<FluxTable> tables = queryApi.query(flux);
// for (FluxTable fluxTable : tables) {
// List<FluxRecord> records = fluxTable.getRecords();
// for (FluxRecord fluxRecord : records) {
// System.out.println("time: "+fluxRecord.getTime() +" key:"+fluxRecord.getField()+" value: " + fluxRecord.getValueByKey("_value")+" measurement: " + fluxRecord.getMeasurement());
//
// }
// }
return queryApi.query(flux);
}
}

View File

@@ -0,0 +1,23 @@
package com.cnbm.influx.constant;
import com.influxdb.LogLevel;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/7/1 9:18
*/
public class Constant {
public static final String url = "http://192.168.0.170:8086";
public static final String token = "lkBsC27QZr1W50BSPlGxpTqNNpwuUk5uz1dZZRPSPbCG5VmNDDUo8P3UkZIhGWwfJwkuz6ZGZ7Et4_KBaG3gHw==";
public static final String org = "qgs";
public static final String bucket = "qgs-bucket";
public static final String username = "caixiang";
public static final String password = "25112856";
public static final LogLevel logLevel = LogLevel.BODY;
public static final LogLevel readTimeout = LogLevel.BODY;
public static final LogLevel writeTimeout = LogLevel.BODY;
public static final LogLevel connectTimeout = LogLevel.BODY;
}

View File

@@ -0,0 +1,78 @@
package com.cnbm.influx.controller;
import com.cnbm.influx.config.InfluxClient;
import com.cnbm.influx.template.Event;
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
@RestController
@RequestMapping("/influx")
public class S7DemoController {
private static final Logger logger = LoggerFactory.getLogger(S7DemoController.class);
@Autowired
InfluxDBClient influxDBClient;
// try (WriteApi writeApi = influxDBClient.makeWriteApi()) {
// Temperature temperature = new Temperature();
// temperature.setLocation("east");
// temperature.setValue(106.2D);
// temperature.setTime(Instant.now());
// writeApi.writeMeasurement(WritePrecision.NS,temperature);
// }
//
// try (WriteApi writeApi = influxDBClient.makeWriteApi()) {
// Point point = Point.measurement("temperature")
// .addTag("location","south")
// .addTag("owner","wxm")
// .addField("wxm",230.8);
// writeApi.writePoint(point);
// }
@PostMapping("/insertBatch")
public void insertBatch() throws InterruptedException {
// List<Event> list = new ArrayList<>();
//
// for(int i=0;i<99;i++){
// //Thread.sleep(1000);
// Event event = new Event();
// event.time = Instant.now();
// event.transationId = "asas"+i;
// event.argName = "arg5";
// event.argValue = new Double(i);
// list.add(event);
// }
// influxService.batchInsert(list);
}
public Point insert(Event event, String measurement){
Point point = Point.measurement(measurement)
.addTag("transationId", event.getTransationId())
.addTag("argName", event.getArgName())
.addField("argValue", event.getArgValue())
.time(event.getTime().toEpochMilli(), WritePrecision.MS);
return point;
}
@PostMapping("/insert")
public void insert() throws InterruptedException {
Event event = new Event();
event.setTime(Instant.now());
event.setTransationId("asasd11");
event.setArgName("argName11");
event.setArgValue(7d);
Point asProcessCompleteEvent = insert(event, "ASProcessCompleteEvent");
influxDBClient.makeWriteApi().writePoint(asProcessCompleteEvent);
}
}

View File

@@ -0,0 +1,30 @@
package com.cnbm.influx.entity;
import lombok.Data;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/6/27 10:46
*/
@Data
public class Header {
private String transationId;
private String messageName;
private String messageType;
private String fromWhere;
private String toWhere;
private String equipmentId;
private String sendTimestamp;
private String argName;
private Double argValue;
}

View File

@@ -0,0 +1,55 @@
/*
* The MIT License
*
* 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.
*/
package com.cnbm.influx.health;
import com.influxdb.client.InfluxDBClient;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.util.Assert;
/**
* {@link //HealthIndicator} for InfluxDB 2.
*
* @author Jakub Bednar (bednar@github)
*/
public class InfluxDB2HealthIndicator extends AbstractHealthIndicator {
private final InfluxDBClient influxDBClient;
public InfluxDB2HealthIndicator(final InfluxDBClient influxDBClient) {
super("InfluxDBClient 2 health check failed");
Assert.notNull(influxDBClient, "InfluxDBClient must not be null");
this.influxDBClient = influxDBClient;
}
@Override
protected void doHealthCheck(final Health.Builder builder) {
boolean success = this.influxDBClient.ping();
if (success) {
builder.up();
} else {
builder.down();
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* The MIT License
*
* 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.
*/
package com.cnbm.influx.health;
import com.cnbm.influx.influx.InfluxDB2AutoConfiguration;
import com.influxdb.client.InfluxDBClient;
import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration;
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.actuate.health.HealthContributor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link InfluxDB2HealthIndicator}.
*
* @author Jakub Bednar
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(InfluxDBClient.class)
@ConditionalOnBean(InfluxDBClient.class)
@ConditionalOnEnabledHealthIndicator("influx")
@AutoConfigureAfter(InfluxDB2AutoConfiguration.class)
public class InfluxDB2HealthIndicatorAutoConfiguration
extends CompositeHealthContributorConfiguration<InfluxDB2HealthIndicator, InfluxDBClient> {
@Bean
@ConditionalOnMissingBean(name = { "influxDB2HealthIndicator", "influxDB2HealthContributor" })
public HealthContributor influxDbHealthContributor(final Map<String, InfluxDBClient> influxDBClients) {
return createContributor(influxDBClients);
}
}

View File

@@ -0,0 +1,71 @@
/*
* The MIT License
*
* 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.
*/
package com.cnbm.influx.influx;
import com.influxdb.client.InfluxDBClientOptions;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import org.springframework.util.StringUtils;
import javax.annotation.Nonnull;
import java.util.Collections;
/**
* @author Jakub Bednar (04/08/2021 11:41)
*/
abstract class AbstractInfluxDB2AutoConfiguration {
protected final InfluxDB2Properties properties;
protected final InfluxDB2OkHttpClientBuilderProvider builderProvider;
protected AbstractInfluxDB2AutoConfiguration(final InfluxDB2Properties properties,
final InfluxDB2OkHttpClientBuilderProvider builderProvider) {
this.properties = properties;
this.builderProvider = builderProvider;
}
@Nonnull
protected InfluxDBClientOptions.Builder makeBuilder() {
OkHttpClient.Builder okHttpBuilder;
if (builderProvider == null) {
okHttpBuilder = new OkHttpClient.Builder()
.protocols(Collections.singletonList(Protocol.HTTP_1_1))
.readTimeout(properties.getReadTimeout())
.writeTimeout(properties.getWriteTimeout())
.connectTimeout(properties.getConnectTimeout());
} else {
okHttpBuilder = builderProvider.get();
}
InfluxDBClientOptions.Builder influxBuilder = InfluxDBClientOptions.builder()
.url(properties.getUrl())
.bucket(properties.getBucket())
.org(properties.getOrg())
.okHttpClient(okHttpBuilder);
if (StringUtils.hasLength(properties.getToken())) {
influxBuilder.authenticateToken(properties.getToken().toCharArray());
} else if (StringUtils.hasLength(properties.getUsername()) && StringUtils.hasLength(properties.getPassword())) {
influxBuilder.authenticate(properties.getUsername(), properties.getPassword().toCharArray());
}
return influxBuilder;
}
}

View File

@@ -0,0 +1,60 @@
/*
* The MIT License
*
* 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.
*/
package com.cnbm.influx.influx;
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.InfluxDBClientFactory;
import com.influxdb.client.InfluxDBClientOptions;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* {@link EnableAutoConfiguration Auto-configuration} for InfluxDB 2.
*
* @author Jakub Bednar (bednar@github) (06/05/2019 13:09)
*/
@Configuration
@ConditionalOnClass(InfluxDBClient.class)
@EnableConfigurationProperties(InfluxDB2Properties.class)
public class InfluxDB2AutoConfiguration extends AbstractInfluxDB2AutoConfiguration {
public InfluxDB2AutoConfiguration(final InfluxDB2Properties properties,
final ObjectProvider<InfluxDB2OkHttpClientBuilderProvider> builderProvider) {
super(properties, builderProvider.getIfAvailable());
}
@Bean
@ConditionalOnProperty("influx.url")
@ConditionalOnMissingBean(InfluxDBClient.class)
public InfluxDBClient influxDBClient() {
InfluxDBClientOptions.Builder influxBuilder = makeBuilder();
return InfluxDBClientFactory.create(influxBuilder.build()).setLogLevel(properties.getLogLevel());
}
}

View File

@@ -0,0 +1,37 @@
/*
* The MIT License
*
* 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.
*/
package com.cnbm.influx.influx;
import okhttp3.OkHttpClient;
import java.util.function.Supplier;
/**
* Provide the {@link OkHttpClient.Builder OkHttpClient.Builder} to use to
* customize the auto-configured {@link com.influxdb.client.InfluxDBClient} instance.
*
* @author Jakub Bednar (bednar@github) (06/05/2019 13:11)
*/
@FunctionalInterface
public interface InfluxDB2OkHttpClientBuilderProvider extends Supplier<OkHttpClient.Builder> {
}

View File

@@ -0,0 +1,178 @@
/*
* The MIT License
*
* 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.
*/
package com.cnbm.influx.influx;
import com.cnbm.influx.constant.Constant;
import com.influxdb.LogLevel;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.time.Duration;
/**
* Configuration properties for InfluxDB 2.
*
* @author Jakub Bednar (bednar@github) (06/05/2019 12:54)
*/
@ConfigurationProperties(prefix = "influx")
public class InfluxDB2Properties {
// public InfluxDB2Properties{
// this.bucket = Constant.bucket;
// this.url = Constant.url;
// this.org = Constant.org;
// this.token = Constant.token;
// this.username = Constant.username;
// this.password = Constant.password;
// }
private static final int DEFAULT_TIMEOUT = 10_000;
/**
* URL to connect to InfluxDB.
*/
private String url = Constant.url;
/**
* Username to use in the basic auth.
*/
private String username = Constant.username;
/**
* Password to use in the basic auth.
*/
private String password = Constant.password;
/**
* Token to use for the authorization.
*/
private String token = Constant.token;
/**
* Default destination organization for writes and queries.
*/
private String org = Constant.org;
/**
* Default destination bucket for writes.
*/
private String bucket = Constant.bucket;
/**
* The log level for logging the HTTP request and HTTP response.
*/
private LogLevel logLevel = LogLevel.NONE;
/**
* Read timeout for {@code OkHttpClient}.
*/
private Duration readTimeout = Duration.ofMillis(DEFAULT_TIMEOUT);
/**
* Write timeout for {@code OkHttpClient}.
*/
private Duration writeTimeout = Duration.ofMillis(DEFAULT_TIMEOUT);
/**
* Connection timeout for {@code OkHttpClient}.
*/
private Duration connectTimeout = Duration.ofMillis(DEFAULT_TIMEOUT);
public String getUrl() {
return url;
}
public void setUrl(final String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
public String getToken() {
return token;
}
public void setToken(final String token) {
this.token = token;
}
public LogLevel getLogLevel() {
return logLevel;
}
public void setLogLevel(final LogLevel logLevel) {
this.logLevel = logLevel;
}
public String getOrg() {
return org;
}
public void setOrg(final String org) {
this.org = org;
}
public String getBucket() {
return bucket;
}
public void setBucket(final String bucket) {
this.bucket = bucket;
}
public Duration getReadTimeout() {
return readTimeout;
}
public void setReadTimeout(final Duration readTimeout) {
this.readTimeout = readTimeout;
}
public Duration getWriteTimeout() {
return writeTimeout;
}
public void setWriteTimeout(final Duration writeTimeout) {
this.writeTimeout = writeTimeout;
}
public Duration getConnectTimeout() {
return connectTimeout;
}
public void setConnectTimeout(final Duration connectTimeout) {
this.connectTimeout = connectTimeout;
}
}

View File

@@ -0,0 +1,24 @@
package com.cnbm.influx.param;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/6/29 10:18
*/
@Data
public class BaseParam implements Serializable {
//page 信息可选
private PageInfo pageInfo;
@NotEmpty(message = "measurement 不能为空")
private String measurement;
@NotNull(message = "查询时间段不能为空")
private Range range;
}

View File

@@ -0,0 +1,24 @@
package com.cnbm.influx.param;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/6/29 10:19
*/
@Data
public class PageInfo {
@Range(min = 1, message = "页码必须大于等于1")
private Integer current;
// @NotNull(message = "每页显示条数不能为空")
@Range(min = 1, max = 1000, message = "每页显示条数范围需在1-1000之间")
private Integer size;
public PageInfo(Integer current,Integer size){
this.current = current;
this.size = size;
}
}

View File

@@ -0,0 +1,31 @@
package com.cnbm.influx.param;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @Desc: "influx 查询条件构造"
* @Author: caixiang
* @DATE: 2022/6/29 10:17
*
* 注意:
* 必填
* ① measurement 不能为空
* ② 时间段 不能为空
* ③ bucket 不能为空
* 非必填
* ① 分页信息可选
* ② tag
*
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class QueryDataParam extends BaseParam{
private Tag tag;
//查询的时候,需要忽略的字段。(transationId是唯一标识会对 最终的查询结果集产生影响)
private String dropedTagName;
private String bucket;
}

View File

@@ -0,0 +1,30 @@
package com.cnbm.influx.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.time.Instant;
/**
* @Desc: "influxdb查询 时间范围"
* @Author: caixiang
* @DATE: 2022/6/29 11:14
*/
@Data
public class Range {
@NotNull(message = "起始时间不能为空")
private Instant begin;
@NotNull(message = "终点时间不能为空")
private Instant end;
public Range(Instant begin,Instant end){
this.begin = begin;
this.end = end;
}
// public static void main(String[] args) {
// Date date = new Date();
// System.out.println(date.toInstant().toString());
// }
}

View File

@@ -0,0 +1,19 @@
package com.cnbm.influx.param;
import lombok.Data;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/6/29 14:38
*/
@Data
public class Tag {
private String tagName;
private String tagValue;
public Tag(String tagName,String tagValue){
this.tagName = tagName;
this.tagValue = tagValue;
}
}

View File

@@ -0,0 +1,24 @@
package com.cnbm.influx.template;
import com.influxdb.annotations.Column;
import com.influxdb.annotations.Measurement;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.time.Instant;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/6/25 11:13
*/
@Data
public class Event {
private Instant time;
private String transationId;
private String argName;
private Double argValue;
}

View File

@@ -0,0 +1,28 @@
package com.cnbm.influx.template;
import com.influxdb.annotations.Column;
import com.influxdb.annotations.Measurement;
import java.time.Instant;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/6/22 15:52
*/
//Temperature.java
@Measurement(name = "temperature")
public class Temperature {
@Column(tag = true)
public String location;
@Column
public Double value;
@Column
public String type;
@Column(timestamp = true)
public Instant time;
}

View File

@@ -0,0 +1,17 @@
influx:
url: http://192.168.0.170:8086 # URL to connect to InfluxDB.
username: caixiang # Username to use in the basic auth.
password: 251128856 # Password to use in the basic auth.
token: lkBsC27QZr1W50BSPlGxpTqNNpwuUk5uz1dZZRPSPbCG5VmNDDUo8P3UkZIhGWwfJwkuz6ZGZ7Et4_KBaG3gHw== # Token to use for the authorization.
org: qgs # Default destination organization for writes and queries.
bucket: qgs-bucket # Default destination bucket for writes.
logLevel: BODY # The log level for logging the HTTP request and HTTP response. (Default: NONE)
readTimeout: 5s # Read timeout for OkHttpClient. (Default: 10s)
writeTimeout: 5s # Write timeout for OkHttpClient. (Default: 10s)
connectTimeout: 5s # Connection timeout for OkHttpClient. (Default: 10s)
# management.health.influx.enabled=true # Whether to enable InfluxDB 2.x health check.
management:
health:
influxdb:
enabled: true

52
ym-schedule-task/pom.xml Normal file
View File

@@ -0,0 +1,52 @@
<?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>ym-pass</artifactId>
<groupId>com.cnbm</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ym-schedule-task</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<quartz.version>2.3.2</quartz.version>
</properties>
<dependencies>
<dependency>
<groupId>com.cnbm</groupId>
<artifactId>ym-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.cnbm</groupId>
<artifactId>ym-admin</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
<exclusions>
<exclusion>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
</exclusion>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java6</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,58 @@
package com.cnbm.scheduletask.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
/**
* @Author weihongyang
* @Date 2022/6/23 4:30 PM
* @Version 1.0
*/
@Configuration
public class ScheduleConfig {
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
//quartz参数
Properties prop = new Properties();
prop.put("org.quartz.scheduler.instanceName", "RenrenScheduler");
prop.put("org.quartz.scheduler.instanceId", "AUTO");
//线程池配置
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "20");
prop.put("org.quartz.threadPool.threadPriority", "5");
//JobStore配置
prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
//集群配置
prop.put("org.quartz.jobStore.isClustered", "true");
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
//PostgreSQL数据库需要打开此注释
//prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
factory.setQuartzProperties(prop);
factory.setSchedulerName("RenrenScheduler");
//延时启动
factory.setStartupDelay(30);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
//可选QuartzScheduler 启动时更新己存在的Job这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
factory.setOverwriteExistingJobs(true);
//设置自动启动默认为true
factory.setAutoStartup(true);
return factory;
}
}

View File

@@ -0,0 +1,125 @@
package com.cnbm.scheduletask.controller;
import com.cnbm.admin.annotation.LogOperation;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.page.PageData;
import com.cnbm.common.utils.Result;
import com.cnbm.common.validator.ValidatorUtils;
import com.cnbm.common.validator.group.AddGroup;
import com.cnbm.common.validator.group.DefaultGroup;
import com.cnbm.common.validator.group.UpdateGroup;
import com.cnbm.scheduletask.dto.ScheduleJobDTO;
import com.cnbm.scheduletask.service.ScheduleJobService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import java.util.Map;
/**
* @Author weihongyang
* @Date 2022/6/24 8:57 AM
* @Version 1.0
*/
@RestController
@RequestMapping("/sys/schedule")
@Api(tags="定时任务")
public class ScheduleJobController {
@Autowired
private ScheduleJobService scheduleJobService;
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = "beanName", value = "beanName", paramType = "query", dataTypeClass=String.class)
})
@PreAuthorize("@ex.hasAuthority('sys:schedule:page')")
public Result<PageData<ScheduleJobDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
PageData<ScheduleJobDTO> page = scheduleJobService.page(params);
return new Result<PageData<ScheduleJobDTO>>().ok(page);
}
@GetMapping("{id}")
@ApiOperation("信息")
@PreAuthorize("@ex.hasAuthority('sys:schedule:info')")
public Result<ScheduleJobDTO> info(@PathVariable("id") Long id){
ScheduleJobDTO schedule = scheduleJobService.get(id);
return new Result<ScheduleJobDTO>().ok(schedule);
}
@PostMapping
@ApiOperation("保存")
@LogOperation("保存")
@PreAuthorize("@ex.hasAuthority('sys:schedule:save')")
public Result save(@RequestBody ScheduleJobDTO dto){
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
scheduleJobService.save(dto);
return new Result();
}
@PutMapping
@ApiOperation("修改")
@LogOperation("修改")
@PreAuthorize("@ex.hasAuthority('sys:schedule:update')")
public Result update(@RequestBody ScheduleJobDTO dto){
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
scheduleJobService.update(dto);
return new Result();
}
@DeleteMapping
@ApiOperation("删除")
@LogOperation("删除")
@PreAuthorize("@ex.hasAuthority('sys:schedule:delete')")
public Result delete(@RequestBody Long[] ids){
scheduleJobService.deleteBatch(ids);
return new Result();
}
@PutMapping("/run")
@ApiOperation("立即执行")
@LogOperation("立即执行")
@PreAuthorize("@ex.hasAuthority('sys:schedule:run')")
public Result run(@RequestBody Long[] ids){
scheduleJobService.run(ids);
return new Result();
}
@PutMapping("/pause")
@ApiOperation("暂停")
@LogOperation("暂停")
@PreAuthorize("@ex.hasAuthority('sys:schedule:pause')")
public Result pause(@RequestBody Long[] ids){
scheduleJobService.pause(ids);
return new Result();
}
@PutMapping("/resume")
@ApiOperation("恢复")
@LogOperation("恢复")
@PreAuthorize("@ex.hasAuthority('sys:schedule:resume')")
public Result resume(@RequestBody Long[] ids){
scheduleJobService.resume(ids);
return new Result();
}
}

View File

@@ -0,0 +1,55 @@
package com.cnbm.scheduletask.controller;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.page.PageData;
import com.cnbm.common.utils.Result;
import com.cnbm.scheduletask.dto.ScheduleJobLogDTO;
import com.cnbm.scheduletask.service.ScheduleJobLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import java.util.Map;
/**
* @Author weihongyang
* @Date 2022/6/24 8:58 AM
* @Version 1.0
*/
@RestController
@RequestMapping("/sys/scheduleLog")
@Api(tags="定时任务日志")
public class ScheduleJobLogController {
@Autowired
private ScheduleJobLogService scheduleJobLogService;
@GetMapping("page")
@ApiOperation("分页")
@ApiImplicitParams({
@ApiImplicitParam(name = Constant.PAGE, value = "当前页码从1开始", paramType = "query", required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataTypeClass=Integer.class) ,
@ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = Constant.ORDER, value = "排序方式,可选值(asc、desc)", paramType = "query", dataTypeClass=String.class) ,
@ApiImplicitParam(name = "jobId", value = "jobId", paramType = "query", dataType="String")
})
@PreAuthorize("@ex.hasAuthority('sys:schedule:log')")
public Result<PageData<ScheduleJobLogDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
PageData<ScheduleJobLogDTO> page = scheduleJobLogService.page(params);
return new Result<PageData<ScheduleJobLogDTO>>().ok(page);
}
@GetMapping("{id}")
@ApiOperation("信息")
@PreAuthorize("@ex.hasAuthority('sys:schedule:log')")
public Result<ScheduleJobLogDTO> info(@PathVariable("id") Long id){
ScheduleJobLogDTO log = scheduleJobLogService.get(id);
return new Result<ScheduleJobLogDTO>().ok(log);
}
}

View File

@@ -0,0 +1,21 @@
package com.cnbm.scheduletask.dao;
import com.cnbm.common.dao.BaseDao;
import com.cnbm.scheduletask.entity.ScheduleJobEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.Map;
/**
* @Author weihongyang
* @Date 2022/6/23 4:48 PM
* @Version 1.0
*/
@Mapper
public interface ScheduleJobDao extends BaseDao<ScheduleJobEntity> {
/**
* 批量更新状态
*/
int updateBatch(Map<String, Object> map);
}

View File

@@ -0,0 +1,15 @@
package com.cnbm.scheduletask.dao;
import com.cnbm.common.dao.BaseDao;
import com.cnbm.scheduletask.entity.ScheduleJobLogEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* @Author weihongyang
* @Date 2022/6/23 4:48 PM
* @Version 1.0
*/
@Mapper
public interface ScheduleJobLogDao extends BaseDao<ScheduleJobLogEntity> {
}

View File

@@ -0,0 +1,56 @@
package com.cnbm.scheduletask.dto;
import com.cnbm.common.validator.group.AddGroup;
import com.cnbm.common.validator.group.DefaultGroup;
import com.cnbm.common.validator.group.UpdateGroup;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.io.Serializable;
import java.util.Date;
/**
* @Author weihongyang
* @Date 2022/6/23 4:49 PM
* @Version 1.0
*/
@Data
@ApiModel(value = "定时任务")
public class ScheduleJobDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "id")
@Null(message="{id.null}", groups = AddGroup.class)
@NotNull(message="{id.require}", groups = UpdateGroup.class)
private Long id;
@ApiModelProperty(value = "spring bean名称")
@NotBlank(message = "{schedule.bean.require}", groups = DefaultGroup.class)
private String beanName;
@ApiModelProperty(value = "参数")
private String params;
@ApiModelProperty(value = "cron表达式")
@NotBlank(message = "{schedule.cron.require}", groups = DefaultGroup.class)
private String cronExpression;
@ApiModelProperty(value = "任务状态 0暂停 1正常")
@Range(min=0, max=1, message = "{schedule.status.range}", groups = DefaultGroup.class)
private Integer status;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "创建时间")
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Date createDate;
}

View File

@@ -0,0 +1,45 @@
package com.cnbm.scheduletask.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Author weihongyang
* @Date 2022/6/23 4:49 PM
* @Version 1.0
*/
@Data
@ApiModel(value = "定时任务日志")
public class ScheduleJobLogDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "任务id")
private Long jobId;
@ApiModelProperty(value = "spring bean名称")
private String beanName;
@ApiModelProperty(value = "参数")
private String params;
@ApiModelProperty(value = "任务状态 0失败 1成功")
private Integer status;
@ApiModelProperty(value = "失败信息")
private String error;
@ApiModelProperty(value = "耗时(单位:毫秒)")
private Integer times;
@ApiModelProperty(value = "创建时间")
private Date createDate;
}

View File

@@ -0,0 +1,53 @@
package com.cnbm.scheduletask.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cnbm.common.entity.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* @Author weihongyang
* @Date 2022/6/23 4:47 PM
* @Version 1.0
*/
@Data
@EqualsAndHashCode(callSuper=false)
@TableName("schedule_job")
public class ScheduleJobEntity extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* spring bean名称
*/
private String beanName;
/**
* 参数
*/
private String params;
/**
* cron表达式
*/
private String cronExpression;
/**
* 任务状态 0暂停 1正常
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 更新者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updater;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateDate;
}

View File

@@ -0,0 +1,54 @@
package com.cnbm.scheduletask.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Author weihongyang
* @Date 2022/6/23 4:47 PM
* @Version 1.0
*/
@Data
@TableName("schedule_job_log")
public class ScheduleJobLogEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId
private Long id;
/**
* 任务id
*/
private Long jobId;
/**
* spring bean名称
*/
private String beanName;
/**
* 参数
*/
private String params;
/**
* 任务状态 0失败 1成功
*/
private Integer status;
/**
* 失败信息
*/
private String error;
/**
* 耗时(单位:毫秒)
*/
private Integer times;
/**
* 创建时间
*/
private Date createDate;
}

View File

@@ -0,0 +1,39 @@
package com.cnbm.scheduletask.init;
import com.cnbm.scheduletask.dao.ScheduleJobDao;
import com.cnbm.scheduletask.entity.ScheduleJobEntity;
import com.cnbm.scheduletask.utils.ScheduleUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Author weihongyang
* @Date 2022/6/23 4:46 PM
* @Version 1.0
*/
@Component
public class JobCommandLineRunner implements CommandLineRunner {
@Autowired
private Scheduler scheduler;
@Autowired
private ScheduleJobDao scheduleJobDao;
@Override
public void run(String... args) {
List<ScheduleJobEntity> scheduleJobList = scheduleJobDao.selectList(null);
for(ScheduleJobEntity scheduleJob : scheduleJobList){
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId());
//如果不存在,则创建
if(cronTrigger == null) {
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
}else {
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
}
}
}
}

View File

@@ -0,0 +1,20 @@
package com.cnbm.scheduletask.service;
import com.cnbm.common.page.PageData;
import com.cnbm.common.service.BaseService;
import com.cnbm.scheduletask.dto.ScheduleJobLogDTO;
import com.cnbm.scheduletask.entity.ScheduleJobLogEntity;
import java.util.Map;
/**
* @Author weihongyang
* @Date 2022/6/23 4:44 PM
* @Version 1.0
*/
public interface ScheduleJobLogService extends BaseService<ScheduleJobLogEntity> {
PageData<ScheduleJobLogDTO> page(Map<String, Object> params);
ScheduleJobLogDTO get(Long id);
}

View File

@@ -0,0 +1,56 @@
package com.cnbm.scheduletask.service;
import com.cnbm.common.page.PageData;
import com.cnbm.common.service.BaseService;
import com.cnbm.scheduletask.dto.ScheduleJobDTO;
import com.cnbm.scheduletask.entity.ScheduleJobEntity;
import java.util.Map;
/**
* @Author weihongyang
* @Date 2022/6/23 4:43 PM
* @Version 1.0
*/
public interface ScheduleJobService extends BaseService<ScheduleJobEntity> {
PageData<ScheduleJobDTO> page(Map<String, Object> params);
ScheduleJobDTO get(Long id);
/**
* 保存定时任务
*/
void save(ScheduleJobDTO dto);
/**
* 更新定时任务
*/
void update(ScheduleJobDTO dto);
/**
* 批量删除定时任务
*/
void deleteBatch(Long[] ids);
/**
* 批量更新定时任务状态
*/
int updateBatch(Long[] ids, int status);
/**
* 立即执行
*/
void run(Long[] ids);
/**
* 暂停运行
*/
void pause(Long[] ids);
/**
* 恢复运行
*/
void resume(Long[] ids);
}

View File

@@ -0,0 +1,51 @@
package com.cnbm.scheduletask.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.page.PageData;
import com.cnbm.common.service.impl.BaseServiceImpl;
import com.cnbm.common.utils.ConvertUtils;
import com.cnbm.scheduletask.dao.ScheduleJobLogDao;
import com.cnbm.scheduletask.dto.ScheduleJobLogDTO;
import com.cnbm.scheduletask.entity.ScheduleJobLogEntity;
import com.cnbm.scheduletask.service.ScheduleJobLogService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @Author weihongyang
* @Date 2022/6/23 4:46 PM
* @Version 1.0
*/
@Service
public class ScheduleJobLogServiceImpl extends BaseServiceImpl<ScheduleJobLogDao, ScheduleJobLogEntity> implements ScheduleJobLogService {
@Override
public PageData<ScheduleJobLogDTO> page(Map<String, Object> params) {
IPage<ScheduleJobLogEntity> page = baseDao.selectPage(
getPage(params, Constant.CREATE_DATE, false),
getWrapper(params)
);
return getPageData(page, ScheduleJobLogDTO.class);
}
private QueryWrapper<ScheduleJobLogEntity> getWrapper(Map<String, Object> params){
String jobId = (String)params.get("jobId");
QueryWrapper<ScheduleJobLogEntity> wrapper = new QueryWrapper<>();
wrapper.eq(StringUtils.isNotBlank(jobId), "job_id", jobId);
return wrapper;
}
@Override
public ScheduleJobLogDTO get(Long id) {
ScheduleJobLogEntity entity = baseDao.selectById(id);
return ConvertUtils.sourceToTarget(entity, ScheduleJobLogDTO.class);
}
}

View File

@@ -0,0 +1,127 @@
package com.cnbm.scheduletask.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.page.PageData;
import com.cnbm.common.service.impl.BaseServiceImpl;
import com.cnbm.common.utils.ConvertUtils;
import com.cnbm.scheduletask.dao.ScheduleJobDao;
import com.cnbm.scheduletask.dto.ScheduleJobDTO;
import com.cnbm.scheduletask.entity.ScheduleJobEntity;
import com.cnbm.scheduletask.service.ScheduleJobService;
import com.cnbm.scheduletask.utils.ScheduleUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* @Author weihongyang
* @Date 2022/6/23 4:45 PM
* @Version 1.0
*/
@Service
public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
@Autowired
private Scheduler scheduler;
@Override
public PageData<ScheduleJobDTO> page(Map<String, Object> params) {
IPage<ScheduleJobEntity> page = baseDao.selectPage(
getPage(params, Constant.CREATE_DATE, false),
getWrapper(params)
);
return getPageData(page, ScheduleJobDTO.class);
}
@Override
public ScheduleJobDTO get(Long id) {
ScheduleJobEntity entity = baseDao.selectById(id);
return ConvertUtils.sourceToTarget(entity, ScheduleJobDTO.class);
}
private QueryWrapper<ScheduleJobEntity> getWrapper(Map<String, Object> params){
String beanName = (String)params.get("beanName");
QueryWrapper<ScheduleJobEntity> wrapper = new QueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(beanName), "bean_name", beanName);
return wrapper;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void save(ScheduleJobDTO dto) {
ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
entity.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
this.insert(entity);
ScheduleUtils.createScheduleJob(scheduler, entity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(ScheduleJobDTO dto) {
ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
ScheduleUtils.updateScheduleJob(scheduler, entity);
this.updateById(entity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteBatch(Long[] ids) {
for(Long id : ids){
ScheduleUtils.deleteScheduleJob(scheduler, id);
}
//删除数据
this.deleteBatchIds(Arrays.asList(ids));
}
@Override
public int updateBatch(Long[] ids, int status){
Map<String, Object> map = new HashMap<>(2);
map.put("ids", ids);
map.put("status", status);
return baseDao.updateBatch(map);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void run(Long[] ids) {
for(Long id : ids){
ScheduleUtils.run(scheduler, this.selectById(id));
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void pause(Long[] ids) {
for(Long id : ids){
ScheduleUtils.pauseJob(scheduler, id);
}
updateBatch(ids, Constant.ScheduleStatus.PAUSE.getValue());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void resume(Long[] ids) {
for(Long id : ids){
ScheduleUtils.resumeJob(scheduler, id);
}
updateBatch(ids, Constant.ScheduleStatus.NORMAL.getValue());
}
}

View File

@@ -0,0 +1,16 @@
package com.cnbm.scheduletask.task;
/**
* @Author weihongyang
* @Date 2022/6/23 4:41 PM
* @Version 1.0
*/
public interface ITask {
/**
* 执行定时任务接口
*
* @param params 参数多参数使用JSON数据
*/
void run(String params);
}

View File

@@ -0,0 +1,21 @@
package com.cnbm.scheduletask.task;
import lombok.extern.log4j.Log4j2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* @Author weihongyang
* @Date 2022/6/23 4:41 PM
* @Version 1.0
*/
@Log4j2
@Component("testTask")
public class TestTask implements ITask{
@Override
public void run(String params){
log.info("TestTask定时任务正在执行参数为{}", params);
}
}

View File

@@ -0,0 +1,71 @@
package com.cnbm.scheduletask.utils;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.exception.ExceptionUtils;
import com.cnbm.common.utils.SpringContextUtils;
import com.cnbm.scheduletask.entity.ScheduleJobEntity;
import com.cnbm.scheduletask.entity.ScheduleJobLogEntity;
import com.cnbm.scheduletask.service.ScheduleJobLogService;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;
import java.util.Date;
/**
* @Author weihongyang
* @Date 2022/6/23 4:38 PM
* @Version 1.0
*/
public class ScheduleJob extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
protected void executeInternal(JobExecutionContext context) {
ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap().
get(ScheduleUtils.JOB_PARAM_KEY);
//数据库保存执行记录
ScheduleJobLogEntity log = new ScheduleJobLogEntity();
log.setJobId(scheduleJob.getId());
log.setBeanName(scheduleJob.getBeanName());
log.setParams(scheduleJob.getParams());
log.setCreateDate(new Date());
//任务开始时间
long startTime = System.currentTimeMillis();
try {
//执行任务
logger.info("任务准备执行任务ID{}", scheduleJob.getId());
Object target = SpringContextUtils.getBean(scheduleJob.getBeanName());
Method method = target.getClass().getDeclaredMethod("run", String.class);
method.invoke(target, scheduleJob.getParams());
//任务执行总时长
long times = System.currentTimeMillis() - startTime;
log.setTimes((int)times);
//任务状态
log.setStatus(Constant.SUCCESS);
logger.info("任务执行完毕任务ID{} 总共耗时:{} 毫秒", scheduleJob.getId(), times);
} catch (Exception e) {
logger.error("任务执行失败任务ID{}", scheduleJob.getId(), e);
//任务执行总时长
long times = System.currentTimeMillis() - startTime;
log.setTimes((int)times);
//任务状态
log.setStatus(Constant.FAIL);
log.setError(ExceptionUtils.getErrorStackTrace(e));
}finally {
//获取spring bean
ScheduleJobLogService scheduleJobLogService = SpringContextUtils.getBean(ScheduleJobLogService.class);
scheduleJobLogService.insert(log);
}
}
}

View File

@@ -0,0 +1,154 @@
package com.cnbm.scheduletask.utils;
import com.cnbm.common.constant.Constant;
import com.cnbm.common.exception.ErrorCode;
import com.cnbm.common.exception.RenException;
import com.cnbm.scheduletask.entity.ScheduleJobEntity;
import org.quartz.*;
/**
* @Author weihongyang
* @Date 2022/6/23 4:40 PM
* @Version 1.0
*/
public class ScheduleUtils {
private final static String JOB_NAME = "TASK_";
/**
* 任务调度参数key
*/
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
/**
* 获取触发器key
*/
public static TriggerKey getTriggerKey(Long jobId) {
return TriggerKey.triggerKey(JOB_NAME + jobId);
}
/**
* 获取jobKey
*/
public static JobKey getJobKey(Long jobId) {
return JobKey.jobKey(JOB_NAME + jobId);
}
/**
* 获取表达式触发器
*/
public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
try {
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
} catch (SchedulerException e) {
throw new RenException(ErrorCode.JOB_ERROR, e);
}
}
/**
* 创建定时任务
*/
public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
try {
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getId())).build();
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getId())).withSchedule(scheduleBuilder).build();
//放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
scheduler.scheduleJob(jobDetail, trigger);
//暂停任务
if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
pauseJob(scheduler, scheduleJob.getId());
}
} catch (SchedulerException e) {
throw new RenException(ErrorCode.JOB_ERROR, e);
}
}
/**
* 更新定时任务
*/
public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
try {
TriggerKey triggerKey = getTriggerKey(scheduleJob.getId());
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getId());
//按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//参数
trigger.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
scheduler.rescheduleJob(triggerKey, trigger);
//暂停任务
if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
pauseJob(scheduler, scheduleJob.getId());
}
} catch (SchedulerException e) {
throw new RenException(ErrorCode.JOB_ERROR, e);
}
}
/**
* 立即执行任务
*/
public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
try {
//参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(JOB_PARAM_KEY, scheduleJob);
scheduler.triggerJob(getJobKey(scheduleJob.getId()), dataMap);
} catch (SchedulerException e) {
throw new RenException(ErrorCode.JOB_ERROR, e);
}
}
/**
* 暂停任务
*/
public static void pauseJob(Scheduler scheduler, Long jobId) {
try {
scheduler.pauseJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RenException(ErrorCode.JOB_ERROR, e);
}
}
/**
* 恢复任务
*/
public static void resumeJob(Scheduler scheduler, Long jobId) {
try {
scheduler.resumeJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RenException(ErrorCode.JOB_ERROR, e);
}
}
/**
* 删除定时任务
*/
public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
try {
scheduler.deleteJob(getJobKey(jobId));
} catch (SchedulerException e) {
throw new RenException(ErrorCode.JOB_ERROR, e);
}
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cnbm.scheduletask.dao.ScheduleJobDao">
<!-- 批量更新状态 -->
<update id="updateBatch">
update schedule_job set status = #{status} where id in
<foreach item="id" collection="ids" open="(" separator="," close=")">
#{id}
</foreach>
</update>
</mapper>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cnbm.scheduletask.dao.ScheduleJobLogDao">
</mapper>