This commit is contained in:
parent
de5d9ea54c
commit
f523b8a996
|
@ -1,5 +1,6 @@
|
|||
package com.recovery.admin.boot;
|
||||
|
||||
import com.dtp.core.spring.EnableDynamicTp;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
@ -12,6 +13,7 @@ import org.springframework.context.annotation.ComponentScan;
|
|||
@EnableDiscoveryClient
|
||||
@RefreshScope
|
||||
@EnableFeignClients
|
||||
@EnableDynamicTp
|
||||
@ComponentScan(basePackages = {"com.recovery.admin.boot","com.recovery.common.base"})
|
||||
@MapperScan("com.recovery.admin.boot.mapper")
|
||||
public class AdminApp {
|
||||
|
|
|
@ -83,6 +83,9 @@ public class WebLogAspect {
|
|||
//执行完切面后,将线程共享中的数据源名称清空
|
||||
@After("webLog()")
|
||||
public void after(JoinPoint joinPoint){
|
||||
log.info("清除数据源===========================================");
|
||||
//清除
|
||||
HspHostUtil.clear();
|
||||
DataSourceContextHolder.clearDBType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package com.recovery.admin.boot.config;
|
||||
|
||||
import com.alibaba.cloud.nacos.NacosConfigManager;
|
||||
import com.alibaba.cloud.nacos.NacosConfigProperties;
|
||||
import com.alibaba.nacos.api.config.listener.Listener;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* @author 小工匠
|
||||
* @version 1.0
|
||||
* @mark: show me the code , change the world
|
||||
*/
|
||||
@RefreshScope
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class DynamicThreadPoolConfig implements InitializingBean {
|
||||
|
||||
|
||||
private String coreSize = "5";
|
||||
|
||||
|
||||
private String maxSize = "5";
|
||||
|
||||
private static ThreadPoolExecutor threadPoolExecutor;
|
||||
|
||||
@Autowired
|
||||
private NacosConfigManager nacosConfigManager;
|
||||
|
||||
@Autowired
|
||||
private NacosConfigProperties nacosConfigProperties;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
//按照nacos配置初始化线程池
|
||||
threadPoolExecutor = new ThreadPoolExecutor(Integer.parseInt(coreSize), Integer.parseInt(maxSize), 10L, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(10),
|
||||
new ThreadFactoryBuilder().setNameFormat("c_t_%d").build(),
|
||||
new RejectedExecutionHandler() {
|
||||
@Override
|
||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
||||
log.info("Warn Warn Warn : rejected executed!!!");
|
||||
}
|
||||
});
|
||||
|
||||
//nacos配置变更监听
|
||||
nacosConfigManager.getConfigService().addListener("order-service-dev.yml", nacosConfigProperties.getGroup(),
|
||||
new Listener() {
|
||||
@Override
|
||||
public Executor getExecutor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveConfigInfo(String configInfo) {
|
||||
//配置变更,修改线程池配置
|
||||
log.info("收到Nacos Config Server推来的配置变更,修改线程池配置", configInfo);
|
||||
changeThreadPoolConfig(Integer.parseInt(coreSize), Integer.parseInt(maxSize));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印当前线程池的状态
|
||||
*/
|
||||
public String printThreadPoolStatus() {
|
||||
return String.format("core_size:%s,thread_current_size:%s;" +
|
||||
"thread_max_size:%s;queue_current_size:%s,total_task_count:%s", threadPoolExecutor.getCorePoolSize(),
|
||||
threadPoolExecutor.getActiveCount(), threadPoolExecutor.getMaximumPoolSize(), threadPoolExecutor.getQueue().size(),
|
||||
threadPoolExecutor.getTaskCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* 给线程池增加任务
|
||||
*
|
||||
* @param count
|
||||
*/
|
||||
public void dynamicThreadPoolAddTask(int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
int finalI = i;
|
||||
threadPoolExecutor.execute(() -> {
|
||||
try {
|
||||
log.info("dynamicThreadPoolAddTask->", finalI);
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改线程池核心参数
|
||||
*
|
||||
* @param coreSize
|
||||
* @param maxSize
|
||||
*/
|
||||
private void changeThreadPoolConfig(int coreSize, int maxSize) {
|
||||
threadPoolExecutor.setCorePoolSize(coreSize);
|
||||
threadPoolExecutor.setMaximumPoolSize(maxSize);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ package com.recovery.admin.boot.controller;
|
|||
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.log.Log;
|
||||
import com.recovery.admin.boot.config.DynamicThreadPoolConfig;
|
||||
import com.recovery.admin.boot.service.ISysUserService;
|
||||
import com.recovery.common.base.constant.Constants;
|
||||
import com.recovery.common.base.dto.UserAuthDTO;
|
||||
|
@ -9,6 +11,7 @@ import com.recovery.common.base.result.ApiResult;
|
|||
import com.recovery.common.base.util.HspHostUtil;
|
||||
import com.recovery.common.base.util.RedisUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
|
@ -27,6 +30,8 @@ public class testController {
|
|||
ISysUserService iSysUserService;
|
||||
@Resource
|
||||
RedisUtil redisUtil;
|
||||
@Autowired
|
||||
private DynamicThreadPoolConfig dynamicThreadPool;
|
||||
|
||||
/**
|
||||
* cs
|
||||
|
@ -35,9 +40,19 @@ public class testController {
|
|||
public ApiResult<UserAuthDTO> cs(@RequestParam String name, HttpServletRequest request) {
|
||||
UserAuthDTO authDTO = iSysUserService.getByUsername(name);
|
||||
log.info("测试库:"+authDTO.getStatus());
|
||||
String user = StpUtil.getLoginIdDefaultNull()+"";
|
||||
log.info("111获取线程的数据=="+HspHostUtil.getHspHost());
|
||||
StpUtil.kickoutByTokenValue(Constants.LOGIN_USRE_TOKEN);
|
||||
Thread thread = new Thread(()->{
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
log.info("获取线程的数据=="+HspHostUtil.getHspHost());
|
||||
},"测试线程");
|
||||
thread.start();
|
||||
// StpUtil.logout();
|
||||
dynamicThreadPool.printThreadPoolStatus();
|
||||
return ApiResult.ok(authDTO);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,24 @@ package com.recovery.admin.boot.exception;
|
|||
|
||||
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.exception.NotPermissionException;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import com.recovery.common.base.result.ApiResult;
|
||||
import com.recovery.common.base.result.ResultCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
/**
|
||||
* 全局异常处理
|
||||
*/
|
||||
|
@ -64,11 +75,68 @@ public class GlobalExceptionHandler {
|
|||
else {
|
||||
message = "当前会话未登录";
|
||||
}
|
||||
|
||||
// 返回给前端
|
||||
return ApiResult.failed(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截表单参数校验
|
||||
*/
|
||||
@ResponseBody
|
||||
@ExceptionHandler(BindException.class)
|
||||
public ApiResult bindExceptionHandler(BindException ex) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
BindingResult bindingResult = ex.getBindingResult();
|
||||
if (bindingResult.hasErrors()) {
|
||||
for (int i = 0; i < bindingResult.getAllErrors().size(); i++) {
|
||||
ObjectError error = bindingResult.getAllErrors().get(i);
|
||||
sb.append((i == 0 ? "" : "\n") + error.getDefaultMessage());
|
||||
}
|
||||
}
|
||||
return ApiResult.failed(sb.toString());
|
||||
}
|
||||
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
@ResponseBody
|
||||
public ApiResult handler(ConstraintViolationException ex) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int i = 0;
|
||||
for (ConstraintViolation violation : ex.getConstraintViolations()) {
|
||||
sb.append((++i == 1 ? "" : "\n") + violation.getMessage());
|
||||
}
|
||||
return ApiResult.failed(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求方式不支持
|
||||
*/
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
public ApiResult httpReqMethodNotSupported(HttpRequestMethodNotSupportedException e) {
|
||||
log.error("错误信息:{}", e.getLocalizedMessage());
|
||||
return ApiResult.failed("请求方式不支持");
|
||||
}
|
||||
|
||||
/**
|
||||
* 未登录异常
|
||||
*/
|
||||
@ExceptionHandler(NotLoginException.class)
|
||||
public ApiResult notLoginException(NotLoginException e) {
|
||||
return ApiResult.failed(ResultCode.LOGIN_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用异常
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ApiResult exception(Exception e) {
|
||||
if (e instanceof NotPermissionException){
|
||||
return ApiResult.failed("没有操作权限");
|
||||
}
|
||||
e.printStackTrace();
|
||||
return ApiResult.failed(ResultCode.ACCESS_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
//Security
|
||||
// @ExceptionHandler(value = AccessDeniedException.class)
|
||||
// public void accessDeniedException(AccessDeniedException e) {
|
||||
|
|
|
@ -2,6 +2,9 @@ package com.recovery.admin.boot.interceptor;
|
|||
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.strategy.SaStrategy;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
|
||||
|
@ -36,14 +39,21 @@ public class JwtInterceptor implements HandlerInterceptor {
|
|||
}
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
HashMap<String, String> map=new HashMap<>();
|
||||
// //获取请求参数
|
||||
// RequestWrapper requestWrapper = new RequestWrapper(request);
|
||||
// //这里getBodyString()方法无参数
|
||||
// log.info("RequestBody: {}", requestWrapper.getBodyString());
|
||||
//从http请求头获取token
|
||||
response.setHeader( "Set-Cookie" , "cookiename=httponlyTest;Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");
|
||||
response.setHeader( "Content-Security-Policy" , "default-src 'self'; script-src 'self'; frame-ancestors 'self'");
|
||||
response.setHeader("Access-Control-Allow-Origin", (request).getHeader("Origin"));
|
||||
response.setHeader("Access-Control-Allow-Credentials", "true");
|
||||
response.setHeader("Referrer-Policy","no-referrer");
|
||||
response.setContentType("application/json");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
// 获取当前token(这个token获取的是请求头的token,也可以用 request 获取)
|
||||
String token = StpUtil.getTokenValue();
|
||||
long tokenTimeout = StpUtil.getTokenTimeout();// 获取过期时间
|
||||
//token没过期,过期时间不是-1的时候,每次请求都刷新过期时间
|
||||
if (tokenTimeout != -1){
|
||||
StpUtil.renewTimeout(3600);// 用于token续期
|
||||
}
|
||||
|
||||
String token = request.getHeader(Constants.LOGIN_USRE_TOKEN);
|
||||
if (StringUtils.isEmpty(token)) {
|
||||
throw new BusinessException(ResultCode.LOGIN_ERROR);
|
||||
}
|
||||
|
|
|
@ -19,5 +19,60 @@ spring:
|
|||
prefix: hoe-admin
|
||||
group: dev
|
||||
namespace: 11bfd099-10d6-4f2c-b969-58b76e435cce
|
||||
dynamic:
|
||||
tp:
|
||||
enabled: true
|
||||
enabledBanner: true # 是否开启banner打印,默认true
|
||||
enabledCollect: true # 是否开启监控指标采集,默认false
|
||||
collectorTypes: micrometer,logging # 监控数据采集器类型(logging | micrometer | internal_logging),默认micrometer
|
||||
logPath: /home/logs # 监控日志数据路径,默认 ${user.home}/logs,采集类型非logging不用配置
|
||||
monitorInterval: 5 # 监控时间间隔(报警判断、指标采集),默认5s
|
||||
platforms: # 通知报警平台配置
|
||||
- platform: email
|
||||
receivers: 1650611030@qq.com
|
||||
tomcatTp: # tomcat webserver线程池配置
|
||||
corePoolSize: 100
|
||||
maximumPoolSize: 200
|
||||
keepAliveTime: 60
|
||||
executors: # 动态线程池配置
|
||||
- threadPoolName: dtpExecutor
|
||||
# 线程池别名
|
||||
executorType: common # 线程池类型common、eager:适用于io密集型
|
||||
corePoolSize: 5 # 核心线程数
|
||||
maximumPoolSize: 18 # 最大线程数
|
||||
queueCapacity: 400 # 任务队列容量
|
||||
queueType: VariableLinkedBlockingQueue # 任务队列,查看源码QueueTypeEnum枚举类
|
||||
rejectedHandlerType: CallerRunsPolicy # 拒绝策略,查看RejectedTypeEnum枚举类
|
||||
keepAliveTime: 50
|
||||
allowCoreThreadTimeOut: false # 是否允许核心线程池超时
|
||||
threadNamePrefix: test # 线程名前缀
|
||||
waitForTasksToCompleteOnShutdown: false # 参考spring线程池设计,优雅关闭线程池
|
||||
awaitTerminationSeconds: 5 # 单位(s)
|
||||
preStartAllCoreThreads: false # 是否预热所有核心线程,默认false
|
||||
runTimeout: 200 # 任务执行超时阈值,目前只做告警用,单位(ms)
|
||||
queueTimeout: 100 # 任务在队列等待超时阈值,目前只做告警用,单位(ms)
|
||||
taskWrapperNames: [ "ttl" ] # 任务包装器名称,集成TaskWrapper接口
|
||||
notifyItems: # 报警项,不配置自动会按默认值配置(变更通知、容量报警、活性报警、拒绝报警、任务超时报警)
|
||||
- type: capacity # 报警项类型,查看源码 NotifyTypeEnum枚举类
|
||||
enabled: true
|
||||
threshold: 80 # 报警阈值
|
||||
platforms: [ ding,wechat ] # 可选配置,不配置默认拿上层platforms配置的所以平台
|
||||
interval: 120 # 报警间隔(单位:s)
|
||||
- type: change
|
||||
enabled: true
|
||||
- type: liveness
|
||||
enabled: true
|
||||
threshold: 80
|
||||
- type: reject
|
||||
enabled: true
|
||||
threshold: 1
|
||||
- type: run_timeout
|
||||
enabled: true
|
||||
threshold: 1
|
||||
- type: queue_timeout
|
||||
enabled: true
|
||||
threshold: 1
|
||||
|
||||
server:
|
||||
port: 9002
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ public class WebLogAspect {
|
|||
//执行完切面后,将线程共享中的数据源名称清空
|
||||
@After("webLog()")
|
||||
public void after(JoinPoint joinPoint){
|
||||
log.info("清除数据源===========================================");
|
||||
//清除
|
||||
HspHostUtil.clear();
|
||||
DataSourceContextHolder.clearDBType();
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package com.recovery.common.base.config;
|
||||
|
||||
public class GlobalCorsConfig {
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.recovery.common.base.enums;
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
public enum ErrCodeEnums {
|
||||
}
|
|
@ -20,7 +20,7 @@ public class HspHostUtil {
|
|||
@Resource
|
||||
private static RedisUtil redisUtil;
|
||||
//医院代码
|
||||
private static final ThreadLocal<String> HSP_HSOT = new ThreadLocal<String>();
|
||||
private static final ThreadLocal<String> HSP_HSOT = new InheritableThreadLocal<>();
|
||||
public static String getHspHost() {
|
||||
return HSP_HSOT.get();
|
||||
}
|
||||
|
|
6
pom.xml
6
pom.xml
|
@ -58,6 +58,12 @@
|
|||
<artifactId>sa-token-jwt</artifactId>
|
||||
<version>1.37.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.dynamictp</groupId>
|
||||
<artifactId>dynamic-tp-spring-cloud-starter-nacos</artifactId>
|
||||
<version>1.0.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
|
|
Loading…
Reference in New Issue