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
This commit is contained in:
commit
c15c0e1f1c
7
pom.xml
7
pom.xml
@ -14,7 +14,8 @@
|
|||||||
<module>ym-gateway</module>
|
<module>ym-gateway</module>
|
||||||
<module>ym-barcode</module>
|
<module>ym-barcode</module>
|
||||||
<module>ym-baisc</module>
|
<module>ym-baisc</module>
|
||||||
|
<module>ym-schedule-task</module>
|
||||||
|
<module>ym-websocket</module>
|
||||||
</modules>
|
</modules>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
@ -198,6 +199,10 @@
|
|||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||||
|
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<!-- 阿里云maven仓库 -->
|
<!-- 阿里云maven仓库 -->
|
||||||
|
@ -33,6 +33,11 @@
|
|||||||
<artifactId>jjwt</artifactId>
|
<artifactId>jjwt</artifactId>
|
||||||
<version>0.9.0</version>
|
<version>0.9.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.whvcse</groupId>
|
||||||
|
<artifactId>easy-captcha</artifactId>
|
||||||
|
<version>${captcha.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.cnbm</groupId>
|
<groupId>com.cnbm</groupId>
|
||||||
<artifactId>ym-common</artifactId>
|
<artifactId>ym-common</artifactId>
|
||||||
|
@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||||
@ -59,17 +60,16 @@ public class CorsConfig implements WebMvcConfigurer {
|
|||||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
//日期格式转换
|
|
||||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
|
||||||
mapper.setDateFormat(new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN));
|
|
||||||
mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
|
|
||||||
|
|
||||||
//Long类型转String类型
|
//Long类型转String类型
|
||||||
SimpleModule simpleModule = new SimpleModule();
|
SimpleModule simpleModule = new SimpleModule();
|
||||||
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
||||||
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
|
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
|
||||||
mapper.registerModule(simpleModule);
|
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);
|
converter.setObjectMapper(mapper);
|
||||||
return converter;
|
return converter;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.cnbm.admin.config;
|
package com.cnbm.admin.config;
|
||||||
|
|
||||||
import com.cnbm.admin.filter.JwtAuthenticationTokenFilter;
|
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 com.cnbm.admin.service.impl.UserDetailsServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -18,6 +20,8 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
|||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author weihongyang
|
* @Author weihongyang
|
||||||
* @Date 2022/6/8 1:51 PM
|
* @Date 2022/6/8 1:51 PM
|
||||||
@ -45,6 +49,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserDetailsServiceImpl userDetailsService;
|
private UserDetailsServiceImpl userDetailsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LogoutSuccessHandlerImpl logoutSuccessHandler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private LogoutHandlerImpl logoutHandler;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
@ -56,18 +66,26 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
.and()
|
.and()
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
// 对于登录接口 允许匿名访问
|
// 对于登录接口 允许匿名访问
|
||||||
.antMatchers("/login","/swagger/**","/v2/**",
|
.antMatchers("/login","/doLogout","/swagger/**","/v2/**",
|
||||||
"/doc.html",
|
"/doc.html",
|
||||||
"/swagger-resources/**",
|
"/swagger-resources/**",
|
||||||
"/swagger-ui/**",
|
"/swagger-ui/**",
|
||||||
"/webjars/**").anonymous()
|
"/webjars/**",
|
||||||
|
"/websocket/**",
|
||||||
|
"/captcha").anonymous()
|
||||||
// .antMatchers("/testCors").hasAuthority("system:dept:list222")
|
// .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, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
http.addFilterBefore(jwtAuthenticationTokenFilter, LogoutFilter.class);
|
||||||
//配置异常处理器
|
//配置异常处理器
|
||||||
http.exceptionHandling()
|
http.exceptionHandling()
|
||||||
//配置认证失败处理器
|
//配置认证失败处理器
|
||||||
|
@ -1,19 +1,27 @@
|
|||||||
package com.cnbm.admin.controller;
|
package com.cnbm.admin.controller;
|
||||||
|
|
||||||
|
import com.cnbm.admin.handler.LogoutSuccessHandlerImpl;
|
||||||
import com.cnbm.admin.params.LoginParam;
|
import com.cnbm.admin.params.LoginParam;
|
||||||
|
import com.cnbm.admin.service.CaptchaService;
|
||||||
import com.cnbm.admin.service.LoginService;
|
import com.cnbm.admin.service.LoginService;
|
||||||
import com.cnbm.admin.utils.ResponseResult;
|
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.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author weihongyang
|
* @Author weihongyang
|
||||||
@ -28,11 +36,18 @@ public class LoginController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private LoginService loginService;
|
private LoginService loginService;
|
||||||
|
|
||||||
@RequestMapping("/hello")
|
@Autowired
|
||||||
@PreAuthorize("@ex.hasAuthority('sys:user:page')")
|
private CaptchaService captchaService;
|
||||||
public String hello(){
|
|
||||||
log.info("hello");
|
@GetMapping("/captcha")
|
||||||
return "hello";
|
@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")
|
@PostMapping("/login")
|
||||||
@ -40,4 +55,10 @@ public class LoginController {
|
|||||||
public ResponseResult login(HttpServletRequest request, @RequestBody LoginParam loginParam) {
|
public ResponseResult login(HttpServletRequest request, @RequestBody LoginParam loginParam) {
|
||||||
return loginService.login(request,loginParam);
|
return loginService.login(request,loginParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/doLogout")
|
||||||
|
@ApiOperation(value = "退出")
|
||||||
|
public void logout(){
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,34 +1,30 @@
|
|||||||
package com.cnbm.admin.exception;
|
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.admin.service.SysLogErrorService;
|
||||||
import com.cnbm.common.exception.ErrorCode;
|
import com.cnbm.common.exception.ErrorCode;
|
||||||
import com.cnbm.common.exception.ExceptionUtils;
|
|
||||||
import com.cnbm.common.exception.RenException;
|
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 com.cnbm.common.utils.Result;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DuplicateKeyException;
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
import org.springframework.http.HttpHeaders;
|
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.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author weihongyang
|
* @Author weihongyang
|
||||||
* @Date 2022/6/10 2:05 PM
|
* @Date 2022/6/10 2:05 PM
|
||||||
* @Version 1.0
|
* @Version 1.0
|
||||||
*/
|
*/
|
||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
public class RenExceptionHandler {
|
@Log4j2
|
||||||
private static final Logger logger = LoggerFactory.getLogger(RenExceptionHandler.class);
|
public class YmExceptionHandler {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(YmExceptionHandler.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SysLogErrorService sysLogErrorService;
|
private SysLogErrorService sysLogErrorService;
|
||||||
@ -44,6 +40,35 @@ public class RenExceptionHandler {
|
|||||||
return result;
|
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)
|
@ExceptionHandler(DuplicateKeyException.class)
|
||||||
public Result handleDuplicateKeyException(DuplicateKeyException ex){
|
public Result handleDuplicateKeyException(DuplicateKeyException ex){
|
||||||
Result result = new Result();
|
Result result = new Result();
|
||||||
@ -52,14 +77,14 @@ public class RenExceptionHandler {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExceptionHandler(Exception.class)
|
// @ExceptionHandler(Exception.class)
|
||||||
public Result handleException(Exception ex){
|
// public Result handleException(Exception ex){
|
||||||
logger.error(ex.getMessage(), ex);
|
// logger.error(ex.getMessage(), ex);
|
||||||
|
//
|
||||||
// saveLog(ex);
|
//// saveLog(ex);
|
||||||
|
//
|
||||||
return new Result().error();
|
// return new Result().error();
|
||||||
}
|
// }
|
||||||
//
|
//
|
||||||
// /**
|
// /**
|
||||||
// * 保存异常日志
|
// * 保存异常日志
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -17,11 +17,11 @@ import java.io.Serializable;
|
|||||||
public class LoginParam implements Serializable {
|
public class LoginParam implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ApiModelProperty(value = "用户名", required = true)
|
@ApiModelProperty(value = "用户名", required = true, example = "admin")
|
||||||
@NotBlank(message="用户名不能为空")
|
@NotBlank(message="用户名不能为空")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@ApiModelProperty(value = "密码" , required = true)
|
@ApiModelProperty(value = "密码" , required = true, example = "admin")
|
||||||
@NotBlank(message="密码不能为空")
|
@NotBlank(message="密码不能为空")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
@ -1,9 +1,25 @@
|
|||||||
package com.cnbm.admin.service;
|
package com.cnbm.admin.service;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author weihongyang
|
* @Author weihongyang
|
||||||
* @Date 2022/6/8 8:55 AM
|
* @Date 2022/6/8 8:55 AM
|
||||||
* @Version 1.0
|
* @Version 1.0
|
||||||
*/
|
*/
|
||||||
public interface CaptchaService {
|
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);
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,5 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
public interface LoginService {
|
public interface LoginService {
|
||||||
|
|
||||||
ResponseResult login(HttpServletRequest request, LoginParam loginParam);
|
ResponseResult login(HttpServletRequest request, LoginParam loginParam);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -2,14 +2,17 @@ package com.cnbm.admin.service.impl;
|
|||||||
|
|
||||||
import com.cnbm.admin.entity.LoginUser;
|
import com.cnbm.admin.entity.LoginUser;
|
||||||
import com.cnbm.admin.params.LoginParam;
|
import com.cnbm.admin.params.LoginParam;
|
||||||
|
import com.cnbm.admin.service.CaptchaService;
|
||||||
import com.cnbm.admin.utils.JwtUtil;
|
import com.cnbm.admin.utils.JwtUtil;
|
||||||
import com.cnbm.admin.service.LoginService;
|
import com.cnbm.admin.service.LoginService;
|
||||||
import com.cnbm.admin.utils.ResponseResult;
|
import com.cnbm.admin.utils.ResponseResult;
|
||||||
|
import com.cnbm.common.exception.ErrorCode;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@ -31,8 +34,16 @@ public class LoginServiceImpl implements LoginService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private AuthenticationManager authenticationManager;
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CaptchaService captchaService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseResult login(HttpServletRequest request, LoginParam loginParam) {
|
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());
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginParam.getUsername(),loginParam.getPassword());
|
||||||
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
|
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
|
||||||
if (Objects.isNull(authenticate)) {
|
if (Objects.isNull(authenticate)) {
|
||||||
@ -48,4 +59,5 @@ public class LoginServiceImpl implements LoginService {
|
|||||||
redisTemplate.opsForValue().set("login:"+userid,loginUser);
|
redisTemplate.opsForValue().set("login:"+userid,loginUser);
|
||||||
return new ResponseResult(200,"登录成功",map);
|
return new ResponseResult(200,"登录成功",map);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import com.cnbm.admin.dto.SysUserDTO;
|
|||||||
import com.cnbm.admin.entity.LoginUser;
|
import com.cnbm.admin.entity.LoginUser;
|
||||||
import com.cnbm.admin.entity.SysMenuEntity;
|
import com.cnbm.admin.entity.SysMenuEntity;
|
||||||
import com.cnbm.admin.entity.SysUserEntity;
|
import com.cnbm.admin.entity.SysUserEntity;
|
||||||
|
import com.cnbm.admin.exception.LoginStatusException;
|
||||||
import com.cnbm.admin.service.SysMenuService;
|
import com.cnbm.admin.service.SysMenuService;
|
||||||
import com.cnbm.common.utils.ConvertUtils;
|
import com.cnbm.common.utils.ConvertUtils;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
@ -48,7 +49,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
|
|||||||
throw new UsernameNotFoundException("用户名不存在");
|
throw new UsernameNotFoundException("用户名不存在");
|
||||||
}
|
}
|
||||||
if (sysUserEntity.getStatus() == 0) {
|
if (sysUserEntity.getStatus() == 0) {
|
||||||
throw new DisabledException("该账户已被禁用,请联系管理员");
|
throw new LoginStatusException("该账户已被禁用,请联系管理员");
|
||||||
}
|
}
|
||||||
log.info("sysUserEntity的值是"+sysUserEntity.toString());
|
log.info("sysUserEntity的值是"+sysUserEntity.toString());
|
||||||
log.info("sysUserEntity.getSuperAdmin()=="+sysUserEntity.getSuperAdmin());
|
log.info("sysUserEntity.getSuperAdmin()=="+sysUserEntity.getSuperAdmin());
|
||||||
|
@ -37,6 +37,16 @@
|
|||||||
<artifactId>ym-baisc</artifactId>
|
<artifactId>ym-baisc</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cnbm</groupId>
|
||||||
|
<artifactId>ym-schedule-task</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cnbm</groupId>
|
||||||
|
<artifactId>ym-websocket</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>io.springfox</groupId>
|
||||||
<artifactId>springfox-boot-starter</artifactId>
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
|
@ -41,7 +41,7 @@ public class SwaggerConfig {
|
|||||||
@Bean
|
@Bean
|
||||||
public Docket restApi() {
|
public Docket restApi() {
|
||||||
return new Docket(DocumentationType.SWAGGER_2)
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
.groupName("标准接口")
|
.groupName("全部接口")
|
||||||
.apiInfo(apiInfo("Spring Boot中使用Swagger2构建RESTful APIs", "1.0"))
|
.apiInfo(apiInfo("Spring Boot中使用Swagger2构建RESTful APIs", "1.0"))
|
||||||
.useDefaultResponseMessages(true)
|
.useDefaultResponseMessages(true)
|
||||||
.forCodeGeneration(false)
|
.forCodeGeneration(false)
|
||||||
@ -54,6 +54,22 @@ public class SwaggerConfig {
|
|||||||
.securitySchemes(Arrays.asList(new ApiKey("token", "token", "header")));
|
.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
|
@Bean
|
||||||
public Docket basicApi() {
|
public Docket basicApi() {
|
||||||
return new Docket(DocumentationType.SWAGGER_2)
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
40
ym-gateway/src/main/resources/application-test.yml
Normal file
40
ym-gateway/src/main/resources/application-test.yml
Normal 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
|
@ -24,13 +24,15 @@ spring:
|
|||||||
mvc:
|
mvc:
|
||||||
pathmatch:
|
pathmatch:
|
||||||
matching-strategy: ANT_PATH_MATCHER
|
matching-strategy: ANT_PATH_MATCHER
|
||||||
|
format:
|
||||||
|
date-time: yyyy-MM-dd HH:mm:ss
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 100MB
|
max-file-size: 100MB
|
||||||
max-request-size: 100MB
|
max-request-size: 100MB
|
||||||
enabled: true
|
enabled: true
|
||||||
redis:
|
redis:
|
||||||
database: 0
|
database: 2
|
||||||
host: redis.picaiba.com
|
host: redis.picaiba.com
|
||||||
port: 6380
|
port: 6380
|
||||||
password: '@WSXcde3' # 密码(默认为空)
|
password: '@WSXcde3' # 密码(默认为空)
|
||||||
@ -41,11 +43,10 @@ spring:
|
|||||||
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||||
max-idle: 10 # 连接池中的最大空闲连接
|
max-idle: 10 # 连接池中的最大空闲连接
|
||||||
min-idle: 5 # 连接池中的最小空闲连接
|
min-idle: 5 # 连接池中的最小空闲连接
|
||||||
|
jackson:
|
||||||
# 是否开启redis缓存 true开启 false关闭
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
renren:
|
time-zone: GMT+8
|
||||||
redis:
|
default-property-inclusion: non_null
|
||||||
open: false
|
|
||||||
|
|
||||||
#mybatis
|
#mybatis
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
|
@ -3,6 +3,7 @@ package com.cnbm.generator.engine;
|
|||||||
import com.baomidou.mybatisplus.generator.config.OutputFile;
|
import com.baomidou.mybatisplus.generator.config.OutputFile;
|
||||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||||
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
|
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
|
||||||
|
import com.cnbm.generator.utils.IdWorker;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -21,6 +22,9 @@ public class EnhanceVelocityTemplateEngine extends VelocityTemplateEngine {
|
|||||||
// String otherPath = this.getPathInfo(OutputFile.other);
|
// String otherPath = this.getPathInfo(OutputFile.other);
|
||||||
File file = new File("");
|
File file = new File("");
|
||||||
String path = file.getAbsolutePath();
|
String path = file.getAbsolutePath();
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
objectMap.put("id"+ i, IdWorker.getId());
|
||||||
|
}
|
||||||
customFile.forEach((key, value) -> {
|
customFile.forEach((key, value) -> {
|
||||||
String fileName = "";
|
String fileName = "";
|
||||||
if ("DTO".equals(key)) {
|
if ("DTO".equals(key)) {
|
||||||
@ -29,6 +33,9 @@ public class EnhanceVelocityTemplateEngine extends VelocityTemplateEngine {
|
|||||||
if ("Excel".equals(key)) {
|
if ("Excel".equals(key)) {
|
||||||
fileName = String.format((path+ File.separator +"src/main/java/com/cnbm/generator/code"+ 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);
|
this.outputFile(new File(fileName), objectMap, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
7
ym-generator/src/main/resources/templates/mysql.vm
Normal file
7
ym-generator/src/main/resources/templates/mysql.vm
Normal 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());
|
52
ym-schedule-task/pom.xml
Normal file
52
ym-schedule-task/pom.xml
Normal 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>
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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>
|
@ -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>
|
32
ym-websocket/pom.xml
Normal file
32
ym-websocket/pom.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?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-websocket</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cnbm</groupId>
|
||||||
|
<artifactId>ym-schedule-task</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.cnbm.websocket.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||||
|
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author weihongyang
|
||||||
|
* @Date 2022/6/29 8:58 AM
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSocket
|
||||||
|
public class WebSocketConfig {
|
||||||
|
@Bean
|
||||||
|
public ServerEndpointExporter serverEndpoint(){
|
||||||
|
return new ServerEndpointExporter();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package com.cnbm.websocket.server;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.websocket.OnClose;
|
||||||
|
import javax.websocket.OnMessage;
|
||||||
|
import javax.websocket.OnOpen;
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import javax.websocket.server.ServerEndpoint;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author weihongyang
|
||||||
|
* @Date 2022/6/29 8:59 AM
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
@ServerEndpoint("/websocket/info") // 指定websocket 连接的url
|
||||||
|
public class WebSocketServer {
|
||||||
|
|
||||||
|
private static int onlineCount = 0;
|
||||||
|
|
||||||
|
public static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
private String sessionId;
|
||||||
|
|
||||||
|
@OnOpen
|
||||||
|
public void onOpen(Session session) {
|
||||||
|
log.info("客户端:{}连接成功",session.getId());
|
||||||
|
this.session = session;
|
||||||
|
this.sessionId = session.getId();
|
||||||
|
if (webSocketMap.containsKey(session.getId())){
|
||||||
|
webSocketMap.remove(sessionId);
|
||||||
|
webSocketMap.put(sessionId,this);
|
||||||
|
}else {
|
||||||
|
webSocketMap.put(sessionId,this);
|
||||||
|
addOnlineCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClose
|
||||||
|
public void onClose(Session session) {
|
||||||
|
if (webSocketMap.containsKey(sessionId)) {
|
||||||
|
webSocketMap.remove(sessionId);
|
||||||
|
subOnlineCount();
|
||||||
|
}
|
||||||
|
log.info("客户端:{}连接断开",session.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnMessage
|
||||||
|
public String onMsg(String message,Session session) {
|
||||||
|
log.info("从客户端:{} 收到<--:{}", session.getId(),message);
|
||||||
|
|
||||||
|
String send=message.toUpperCase();
|
||||||
|
String result="客户:%s您好,来自server 的消息:%s";
|
||||||
|
result = String.format(result, session.getId(), send);
|
||||||
|
return "来自server 的消息:" + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendMsg(String message) throws IOException{
|
||||||
|
this.session.getBasicRemote().sendText(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized void addOnlineCount() {
|
||||||
|
WebSocketServer.onlineCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized void subOnlineCount() {
|
||||||
|
WebSocketServer.onlineCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.cnbm.websocket.task;
|
||||||
|
|
||||||
|
import com.cnbm.scheduletask.task.ITask;
|
||||||
|
import com.cnbm.websocket.server.WebSocketServer;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author weihongyang
|
||||||
|
* @Date 2022/6/29 2:01 PM
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Component("sendMessageTask")
|
||||||
|
public class SendMessageTask implements ITask {
|
||||||
|
public void run(String params) {
|
||||||
|
|
||||||
|
Iterator<Map.Entry<String, WebSocketServer>> socketIt = WebSocketServer.webSocketMap.entrySet().iterator();
|
||||||
|
|
||||||
|
|
||||||
|
while (socketIt.hasNext()) {
|
||||||
|
Map.Entry<String, WebSocketServer> socketServerEntry = socketIt.next();
|
||||||
|
try {
|
||||||
|
socketServerEntry.getValue().sendMsg("定时发送:"+new Date().toString());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("sendMessageTask定时任务正在执行,参数为:{}", params);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user