options = new ArrayList<>();
+
+ for (String name : Charset.availableCharsets().keySet()) {
+ StorageSourceParamDef.Options option = new StorageSourceParamDef.Options(name);
+ options.add(option);
+ }
+ return options;
+ }
+
+}
diff --git a/java/src/main/java/com/yfd/platform/annotation/rest/AnonymousGetMapping.java b/java/src/main/java/com/yfd/platform/annotation/rest/AnonymousGetMapping.java
new file mode 100644
index 0000000..01fcc32
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/annotation/rest/AnonymousGetMapping.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.yfd.platform.annotation.rest;
+
+import com.yfd.platform.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation for mapping HTTP {@code GET} requests onto specific handler
+ * methods.
+ *
+ * 支持匿名访问 GetMapping
+ *
+ * @author liaojinlong
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.GET)
+public @interface AnonymousGetMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ *
+ * @since 4.3.5
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/java/src/main/java/com/yfd/platform/aspect/LogAspect.java b/java/src/main/java/com/yfd/platform/aspect/LogAspect.java
new file mode 100644
index 0000000..8f1b2b8
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/aspect/LogAspect.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.aspect;
+
+import com.yfd.platform.system.domain.SysLog;
+import com.yfd.platform.system.mapper.SysUserMapper;
+import com.yfd.platform.system.service.ISysLogService;
+import com.yfd.platform.system.service.IUserService;
+import com.yfd.platform.utils.RequestHolder;
+import com.yfd.platform.utils.SecurityUtils;
+import com.yfd.platform.utils.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+/**
+ * @author
+ * @date 2018-11-24
+ */
+@Component
+@Aspect
+@Slf4j
+public class LogAspect {
+
+ @Resource
+ private final ISysLogService sysLogService;
+
+ @Resource
+ private IUserService userService;
+
+ ThreadLocal currentTime = new ThreadLocal<>();
+
+ public LogAspect(ISysLogService sysLogService) {
+ this.sysLogService = sysLogService;
+ }
+
+ /**
+ * 配置切入点
+ */
+ @Pointcut("@annotation(com.yfd.platform.annotation.Log)")
+ public void logPointcut() {
+ // 该方法无方法体,主要为了让同类中其他方法使用此切入点
+ }
+
+ /**
+ * 配置环绕通知,使用在方法logPointcut()上注册的切入点
+ *
+ * @param joinPoint join point for advice
+ */
+ @Around("logPointcut()")
+ public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ Object result;
+ currentTime.set(System.currentTimeMillis());
+ result = joinPoint.proceed();
+ SysLog log = new SysLog("INFO");
+ currentTime.remove();
+ HttpServletRequest request = RequestHolder.getHttpServletRequest();
+ Map nameInfo = userService.getNameInfo();
+ String nickname = nameInfo.get("nickname");
+ String username = nameInfo.get("username");
+ sysLogService.save(nickname, username, StringUtils.getBrowser(request),
+ StringUtils.getIp(request), joinPoint, log);
+ return result;
+ }
+
+ public String getUsername() {
+ try {
+ return SecurityUtils.getCurrentUsername();
+ } catch (Exception e) {
+ return "";
+ }
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/component/ServerSendEventServer.java b/java/src/main/java/com/yfd/platform/component/ServerSendEventServer.java
new file mode 100644
index 0000000..ca1b1fe
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/component/ServerSendEventServer.java
@@ -0,0 +1,147 @@
+package com.yfd.platform.component;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+
+/**
+ * @author Huhailong
+ * SSE Server send Event 服务器推送服务
+ */
+@Slf4j
+public class ServerSendEventServer {
+
+ /**
+ * 当前连接数
+ */
+ private static AtomicInteger count = new AtomicInteger(0);
+
+ private static Map sseEmitterMap =
+ new ConcurrentHashMap<>();
+
+ public static SseEmitter connect(String userId) {
+ //设置超时时间,0表示不过期,默认是30秒,超过时间未完成会抛出异常
+ SseEmitter sseEmitter = new SseEmitter(0L);
+ //SseEmitter sseEmitter = new SseEmitter();
+ //注册回调
+ sseEmitter.onCompletion(completionCallBack(userId));
+ sseEmitter.onError(errorCallBack(userId));
+ sseEmitter.onTimeout(timeOutCallBack(userId));
+ sseEmitterMap.put(userId, sseEmitter);
+ //数量+1
+ count.getAndIncrement();
+ log.info("create new sse connect ,current user:{}", userId);
+ return sseEmitter;
+ }
+
+ /**
+ * 给指定用户发消息
+ */
+ public static void sendMessage(String userId, String message) {
+ if (sseEmitterMap.containsKey(userId)) {
+ try {
+ sseEmitterMap.get(userId).send(message);
+ } catch (IOException e) {
+ log.error("user id:{}, send message error:{}", userId,
+ e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * 给所有用户发消息
+ */
+ public static void sendMessage(String message) {
+ if (sseEmitterMap != null && !sseEmitterMap.isEmpty()) {
+ sseEmitterMap.forEach((k, v) -> {
+ // 发送消息
+ sendMessage(k, message);
+
+ });
+ }
+ }
+
+ /**
+ * 想多人发送消息,组播
+ */
+ public static void groupSendMessage(String groupId, String message) {
+ if (sseEmitterMap != null && !sseEmitterMap.isEmpty()) {
+ sseEmitterMap.forEach((k, v) -> {
+ try {
+ if (k.startsWith(groupId)) {
+ v.send(message, MediaType.APPLICATION_JSON);
+ }
+ } catch (IOException e) {
+ log.error("user id:{}, send message error:{}", groupId,
+ message);
+ removeUser(k);
+ }
+ });
+ }
+ }
+
+ public static void batchSendMessage(String message) {
+ sseEmitterMap.forEach((k, v) -> {
+ try {
+ v.send(message, MediaType.APPLICATION_JSON);
+ } catch (IOException e) {
+ log.error("user id:{}, send message error:{}", k,
+ e.getMessage());
+ removeUser(k);
+ }
+ });
+ }
+
+ /**
+ * 群发消息
+ */
+ public static void batchSendMessage(String message, Set userIds) {
+ userIds.forEach(userId -> sendMessage(userId, message));
+ }
+
+ public static void removeUser(String userId) {
+ sseEmitterMap.remove(userId);
+ //数量-1
+ count.getAndDecrement();
+ log.info("remove user id:{}", userId);
+ }
+
+ public static List getIds() {
+ return new ArrayList<>(sseEmitterMap.keySet());
+ }
+
+ public static int getUserCount() {
+ return count.intValue();
+ }
+
+ private static Runnable completionCallBack(String userId) {
+ return () -> {
+ log.info("结束连接,{}", userId);
+ removeUser(userId);
+ };
+ }
+
+ private static Runnable timeOutCallBack(String userId) {
+ return () -> {
+ log.info("连接超时,{}", userId);
+ removeUser(userId);
+ };
+ }
+
+ private static Consumer errorCallBack(String userId) {
+ return throwable -> {
+ log.error("连接异常,{}", userId);
+ removeUser(userId);
+ };
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/component/WebSocketServer.java b/java/src/main/java/com/yfd/platform/component/WebSocketServer.java
new file mode 100644
index 0000000..46e0017
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/component/WebSocketServer.java
@@ -0,0 +1,106 @@
+package com.yfd.platform.component;
+
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@ServerEndpoint("/websocket/{token}")
+@Component
+public class WebSocketServer {
+ private static int onlineCount=0;//在线人数
+ private static CopyOnWriteArrayList webSocketSet=new CopyOnWriteArrayList();//在线用户集合
+ private Session session;//与某个客户端的连接会话
+ private String currentUser;
+
+ @OnOpen
+ public void onOpen(@PathParam("token") String token, Session session){
+ this.currentUser = token;
+ this.session=session;
+ webSocketSet.add(this);//加入set中
+ addOnlineCount();
+ System.out.println("有新连接加入!当前在线人数为"+getOnlineCount());
+ allCurrentOnline();
+ }
+
+ @OnClose
+ public void onClose(){
+ webSocketSet.remove(this);
+ subOnlineCount();
+ System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
+ allCurrentOnline();
+ }
+
+ @OnMessage
+ public void onMessage(String message, Session session){
+ System.out.println("来自客户端的消息:"+message);
+ for (WebSocketServer item:webSocketSet){
+ try {
+ item.sendMessage(message);
+ } catch (IOException e) {
+ e.printStackTrace();
+ continue;
+ }
+ }
+ }
+
+ @OnError
+ public void onError(Session session, Throwable throwable){
+ System.out.println("发生错误!");
+ throwable.printStackTrace();
+ }
+
+ public void sendMessage(String message) throws IOException {
+ this.session.getBasicRemote().sendText(message);
+ }
+
+ /**
+ * 获取当前所有在线用户名
+ */
+ public static void allCurrentOnline(){
+ for (WebSocketServer item : webSocketSet) {
+ System.out.println(item.currentUser);
+ }
+ }
+
+ /**
+ * 发送给指定用户
+ */
+ public static void sendMessageTo(String message,String token) throws IOException {
+ for (WebSocketServer item : webSocketSet) {
+ if(item.currentUser.equals(token)){
+ item.session.getBasicRemote().sendText(message);
+ }
+ }
+ }
+
+ /**
+ * 群发自定义消息
+ */
+ public static void sendInfo(String message) throws IOException {
+ System.out.println(message);
+ for (WebSocketServer item : webSocketSet) {
+ try {
+ item.sendMessage(message);
+ } catch (IOException e) {
+ continue;
+ }
+ }
+ }
+
+ public static synchronized int getOnlineCount(){
+ return onlineCount;
+ }
+ public static synchronized void addOnlineCount(){
+ WebSocketServer.onlineCount++;
+ }
+ public static synchronized void subOnlineCount(){
+ WebSocketServer.onlineCount--;
+ }
+
+}
+
+
diff --git a/java/src/main/java/com/yfd/platform/config/FileProperties.java b/java/src/main/java/com/yfd/platform/config/FileProperties.java
new file mode 100644
index 0000000..c179499
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/FileProperties.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "file")
+public class FileProperties {
+
+ /** 文件大小限制 */
+ private Long maxSize;
+
+ /** 头像大小限制 */
+ private Long avatarMaxSize;
+
+ private ElPath mac;
+
+ private ElPath linux;
+
+ private ElPath windows;
+
+ public ElPath getPath(){
+ String os = System.getProperty("os.name");
+ if(os.toLowerCase().startsWith("win")) {
+ return windows;
+ } else if(os.toLowerCase().startsWith("mac")){
+ return mac;
+ }
+ return linux;
+ }
+
+ @Data
+ public static class ElPath{
+
+ private String path;
+
+ private String avatar;
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/GlobalExceptionHandler.java b/java/src/main/java/com/yfd/platform/config/GlobalExceptionHandler.java
new file mode 100644
index 0000000..75725c5
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/GlobalExceptionHandler.java
@@ -0,0 +1,24 @@
+package com.yfd.platform.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * @author LiMengNan
+ * @Date: 2023/3/27 18:07
+ * @Description:
+ */
+@Slf4j
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ @ResponseBody
+ @ExceptionHandler(value = Throwable.class)
+ public ResponseResult handleException(Throwable e) {
+ log.error("message:{}", e.getMessage());
+ return ResponseResult.error(e.getMessage());
+ }
+
+}
diff --git a/java/src/main/java/com/yfd/platform/config/JobRunner.java b/java/src/main/java/com/yfd/platform/config/JobRunner.java
new file mode 100644
index 0000000..c0d451e
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/JobRunner.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.yfd.platform.system.domain.QuartzJob;
+import com.yfd.platform.system.mapper.QuartzJobMapper;
+import com.yfd.platform.utils.QuartzManage;
+import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author
+ * @date 2019-01-07
+ */
+@Component
+@RequiredArgsConstructor
+public class JobRunner implements ApplicationRunner {
+
+ private static final Logger log = LoggerFactory.getLogger(JobRunner.class);
+ private final QuartzJobMapper quartzJobMapper;
+ private final QuartzManage quartzManage;
+
+ /**
+ * 项目启动时重新激活启用的定时任务
+ *
+ * @param applicationArguments /
+ */
+ @Override
+ public void run(ApplicationArguments applicationArguments) {
+ log.info("--------------------注入定时任务---------------------");
+ List quartzJobs =
+ quartzJobMapper.selectList(new LambdaQueryWrapper().eq(QuartzJob::getStatus, "1"));
+ quartzJobs.forEach(quartzManage::addJob);
+ log.info("--------------------定时任务注入完成---------------------");
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java b/java/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java
new file mode 100644
index 0000000..fac58be
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java
@@ -0,0 +1,76 @@
+package com.yfd.platform.config;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.jwt.JWT;
+import cn.hutool.jwt.JWTUtil;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.yfd.platform.component.ServerSendEventServer;
+import com.yfd.platform.constant.Constant;
+import com.yfd.platform.system.domain.LoginUser;
+import com.yfd.platform.system.domain.Message;
+import com.yfd.platform.system.service.IMessageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.annotation.Resource;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
+
+ @Autowired
+ private WebConfig webConfig;
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest httpServletRequest,
+ HttpServletResponse httpServletResponse,
+ FilterChain filterChain) throws ServletException, IOException {
+ //获取token
+ String uri = httpServletRequest.getRequestURI();
+ String token = httpServletRequest.getHeader("token");
+ if (StrUtil.isEmpty(token) || "/user/login".equals(uri)) {
+ filterChain.doFilter(httpServletRequest, httpServletResponse);
+ return;
+ }
+ //解析token
+ boolean isok = JWTUtil.verify(token, "12345678".getBytes());
+ String userid = "";
+ if (isok) {
+ final JWT jwt = JWTUtil.parseToken(token);
+ userid = jwt.getPayload("userid").toString();
+ long expire_time = (Long) jwt.getPayload("expire_time");
+ if (System.currentTimeMillis() > expire_time) {
+ httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Token超过期限!");
+ return;
+ }
+ }
+
+ //从cachekey中获取用户信息
+ String cachekey = "login:" + userid;
+ String jsonstr = webConfig.loginuserCache().get(cachekey);
+ LoginUser loginUser = JSON.parseObject(jsonstr, LoginUser.class);
+ if (ObjectUtil.isEmpty(loginUser)) {
+ httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN,
+ "登录用户已失效!");
+ return;
+ }
+ //存入SecurityContextHolder
+ UsernamePasswordAuthenticationToken authenticationToken =
+ new UsernamePasswordAuthenticationToken(loginUser, null,
+ loginUser.getAuthorities());
+ SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+ webConfig.loginuserCache().put(Constant.TOKEN + userid, token);
+ //放行过滤器
+ filterChain.doFilter(httpServletRequest, httpServletResponse);
+ }
+
+}
diff --git a/java/src/main/java/com/yfd/platform/config/MessageConfig.java b/java/src/main/java/com/yfd/platform/config/MessageConfig.java
new file mode 100644
index 0000000..845f3c8
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/MessageConfig.java
@@ -0,0 +1,50 @@
+package com.yfd.platform.config;
+
+import cn.hutool.cache.Cache;
+import cn.hutool.cache.impl.CacheObj;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.yfd.platform.component.ServerSendEventServer;
+import com.yfd.platform.constant.Constant;
+import com.yfd.platform.system.domain.Message;
+import com.yfd.platform.system.domain.SysUser;
+import com.yfd.platform.system.service.IMessageService;
+import com.yfd.platform.system.service.IUserService;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Iterator;
+
+/**
+ * @author LiMengNan
+ * @Date: 2023/3/24 15:56
+ * @Description:
+ */
+@Component
+public class MessageConfig {
+
+ @Resource
+ private IMessageService messageService;
+
+ @Resource
+ private IUserService userService;
+
+ @Resource
+ private WebConfig webConfig;
+
+ public void sendMessage() {
+ long count =
+ messageService.count(new LambdaQueryWrapper().eq(Message::getStatus, "1"));
+ String userId = userService.getUserInfo().getId();
+ String token = webConfig.loginuserCache().get(Constant.TOKEN + userId);
+ ServerSendEventServer.sendMessage(token, count + "");
+ }
+
+ public void addMessage(Message message) {
+ messageService.save(message);
+ long count =
+ messageService.count(new LambdaQueryWrapper().eq(Message::getStatus, "1"));
+ ServerSendEventServer.sendMessage(count + "");
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/MybatisEnumTypeHandler.java b/java/src/main/java/com/yfd/platform/config/MybatisEnumTypeHandler.java
new file mode 100644
index 0000000..fa8fd0a
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/MybatisEnumTypeHandler.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.baomidou.mybatisplus.annotation.IEnum;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.yfd.platform.utils.TypeUtils;
+import org.apache.ibatis.reflection.DefaultReflectorFactory;
+import org.apache.ibatis.reflection.MetaClass;
+import org.apache.ibatis.reflection.ReflectorFactory;
+import org.apache.ibatis.reflection.invoker.Invoker;
+import org.apache.ibatis.type.BaseTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 自定义枚举属性转换器
+ *
+ * @author hubin
+ * @since 2017-10-11
+ */
+public class MybatisEnumTypeHandler> extends BaseTypeHandler {
+
+ private static final Map TABLE_METHOD_OF_ENUM_TYPES = new ConcurrentHashMap<>();
+ private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();
+ private final Class enumClassType;
+ private final Class> propertyType;
+ private final Invoker getInvoker;
+
+ public MybatisEnumTypeHandler(Class enumClassType) {
+ if (enumClassType == null) {
+ throw new IllegalArgumentException("Type argument cannot be null");
+ }
+ this.enumClassType = enumClassType;
+ MetaClass metaClass = MetaClass.forClass(enumClassType, REFLECTOR_FACTORY);
+ String name = "value";
+ if (!IEnum.class.isAssignableFrom(enumClassType)) {
+ name = findEnumValueFieldName(this.enumClassType).orElseThrow(() -> new IllegalArgumentException(String.format("Could not find @EnumValue in Class: %s.", this.enumClassType.getName())));
+ }
+ this.propertyType = TypeUtils.resolvePrimitiveIfNecessary(metaClass.getGetterType(name));
+ this.getInvoker = metaClass.getGetInvoker(name);
+ }
+
+ /**
+ * 查找标记标记EnumValue字段
+ *
+ * @param clazz class
+ * @return EnumValue字段
+ * @since 3.3.1
+ */
+ public static Optional findEnumValueFieldName(Class> clazz) {
+ if (clazz != null && clazz.isEnum()) {
+ String className = clazz.getName();
+ return Optional.ofNullable(CollectionUtils.computeIfAbsent(TABLE_METHOD_OF_ENUM_TYPES, className, key -> {
+ Optional fieldOptional = findEnumValueAnnotationField(clazz);
+ return fieldOptional.map(Field::getName).orElse(null);
+ }));
+ }
+ return Optional.empty();
+ }
+
+ private static Optional findEnumValueAnnotationField(Class> clazz) {
+ return Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst();
+ }
+
+ /**
+ * 判断是否为MP枚举处理
+ *
+ * @param clazz class
+ * @return 是否为MP枚举处理
+ * @since 3.3.1
+ */
+ public static boolean isMpEnums(Class> clazz) {
+ return clazz != null && clazz.isEnum() && (IEnum.class.isAssignableFrom(clazz) || findEnumValueFieldName(clazz).isPresent());
+ }
+
+ @SuppressWarnings("Duplicates")
+ @Override
+ public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType)
+ throws SQLException {
+ if (jdbcType == null) {
+ ps.setObject(i, this.getValue(parameter));
+ } else {
+ // see r3589
+ ps.setObject(i, this.getValue(parameter), jdbcType.TYPE_CODE);
+ }
+ }
+
+ @Override
+ public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
+ Object value = rs.getObject(columnName);
+ if (null == value && rs.wasNull()) {
+ return null;
+ }
+ return this.valueOf(value);
+ }
+
+ @Override
+ public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
+ Object value = rs.getObject(columnIndex, this.propertyType);
+ if (null == value && rs.wasNull()) {
+ return null;
+ }
+ return this.valueOf(value);
+ }
+
+ @Override
+ public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
+ Object value = cs.getObject(columnIndex, this.propertyType);
+ if (null == value && cs.wasNull()) {
+ return null;
+ }
+ return this.valueOf(value);
+ }
+
+ private E valueOf(Object value) {
+ E[] es = this.enumClassType.getEnumConstants();
+ return Arrays.stream(es).filter((e) -> equalsValue(value, getValue(e))).findAny().orElse(null);
+ }
+
+ /**
+ * 值比较
+ *
+ * @param sourceValue 数据库字段值
+ * @param targetValue 当前枚举属性值
+ * @return 是否匹配
+ * @since 3.3.0
+ */
+ protected boolean equalsValue(Object sourceValue, Object targetValue) {
+ String sValue = StringUtils.toStringTrim(sourceValue);
+ String tValue = StringUtils.toStringTrim(targetValue);
+ if (sourceValue instanceof Number && targetValue instanceof Number
+ && new BigDecimal(sValue).compareTo(new BigDecimal(tValue)) == 0) {
+ return true;
+ }
+ return Objects.equals(sValue, tValue);
+ }
+
+ private Object getValue(Object object) {
+ try {
+ return this.getInvoker.invoke(object, new Object[0]);
+ } catch (ReflectiveOperationException e) {
+ throw ExceptionUtils.mpe(e);
+ }
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/MybitsPlusConfig.java b/java/src/main/java/com/yfd/platform/config/MybitsPlusConfig.java
new file mode 100644
index 0000000..20b9718
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/MybitsPlusConfig.java
@@ -0,0 +1,26 @@
+package com.yfd.platform.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/******************************
+ * 用途说明:
+ * 作者姓名: pcj
+ * 创建时间: 2022/10/24 10:50
+ ******************************/
+@Configuration
+public class MybitsPlusConfig {
+
+ @Bean
+ public MybatisPlusInterceptor mybatisPlusInterceptor() {
+ MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
+ mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+ return mybatisPlusInterceptor;
+ }
+
+
+
+}
diff --git a/java/src/main/java/com/yfd/platform/config/QuartzConfig.java b/java/src/main/java/com/yfd/platform/config/QuartzConfig.java
new file mode 100644
index 0000000..41a36db
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/QuartzConfig.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config;
+
+import org.quartz.Scheduler;
+import org.quartz.spi.TriggerFiredBundle;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.quartz.AdaptableJobFactory;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+/**
+ * 定时任务配置
+ *
+ * @author /
+ * @date 2019-01-07
+ */
+@Configuration
+public class QuartzConfig {
+
+ /**
+ * 解决Job中注入Spring Bean为null的问题
+ */
+ @Component("quartzJobFactory")
+ public static class QuartzJobFactory extends AdaptableJobFactory {
+
+ private final AutowireCapableBeanFactory capableBeanFactory;
+
+ public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
+ this.capableBeanFactory = capableBeanFactory;
+ }
+
+ @Override
+ protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
+
+ //调用父类的方法
+ Object jobInstance = super.createJobInstance(bundle);
+ capableBeanFactory.autowireBean(jobInstance);
+ return jobInstance;
+ }
+ }
+
+ /**
+ * 注入scheduler到spring
+ *
+ * @param quartzJobFactory /
+ * @return Scheduler
+ * @throws Exception /
+ */
+ @Bean(name = "scheduler")
+ public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {
+ SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
+ factoryBean.setJobFactory(quartzJobFactory);
+ factoryBean.afterPropertiesSet();
+ Scheduler scheduler = factoryBean.getScheduler();
+ scheduler.start();
+ return scheduler;
+ }
+
+}
diff --git a/java/src/main/java/com/yfd/platform/config/ResponseResult.java b/java/src/main/java/com/yfd/platform/config/ResponseResult.java
new file mode 100644
index 0000000..d23ea36
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/ResponseResult.java
@@ -0,0 +1,65 @@
+package com.yfd.platform.config;
+
+import java.util.HashMap;
+
+public class ResponseResult extends HashMap {
+
+ private static final long serialVersionUID = 1L;
+
+ // 未登录状态码
+ public static final String CODE_NOT_LOGIN = "401";
+ // 成功状态码
+ public static final String CODE_SUCCESS = "0";
+ // 错误状态码
+ public static final String CODE_ERROR = "1";
+
+ public ResponseResult() {
+ }
+
+ public static ResponseResult unlogin() {
+ return message(CODE_NOT_LOGIN, "未登录");
+ }
+
+ public static ResponseResult error() {
+ return error("操作失败");
+ }
+
+ public static ResponseResult success() {
+ return success("操作成功");
+ }
+
+ public static ResponseResult error(String msg) {
+ ResponseResult json = new ResponseResult();
+ json.put("code", CODE_ERROR);
+ json.put("msg", msg);
+ return json;
+ }
+
+ public static ResponseResult message(String code, String msg) {
+ ResponseResult json = new ResponseResult();
+ json.put("code", code);
+ json.put("msg", msg);
+ return json;
+ }
+
+ public static ResponseResult success(String msg) {
+ ResponseResult json = new ResponseResult();
+ json.put("code", CODE_SUCCESS);
+ json.put("msg", msg);
+ return json;
+ }
+
+ public static ResponseResult successData(Object obj) {
+ ResponseResult json = new ResponseResult();
+ json.put("code", CODE_SUCCESS);
+ json.put("msg", "操作成功");
+ json.put("data", obj);
+ return json;
+ }
+
+
+ public ResponseResult put(String key, Object value) {
+ super.put(key, value);
+ return this;
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/SecurityConfig.java b/java/src/main/java/com/yfd/platform/config/SecurityConfig.java
new file mode 100644
index 0000000..bc55fab
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/SecurityConfig.java
@@ -0,0 +1,111 @@
+package com.yfd.platform.config;
+
+import com.yfd.platform.config.bean.LoginProperties;
+import com.yfd.platform.exception.AccessDeniedHandExcetion;
+import com.yfd.platform.exception.AuthenticationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+@Configuration
+public class SecurityConfig extends WebSecurityConfigurerAdapter
+{
+ // 注入了加密算法
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "login", ignoreUnknownFields = true)
+ public LoginProperties loginProperties() {
+ return new LoginProperties();
+ }
+
+
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception{
+ return super.authenticationManagerBean();
+ }
+ @Autowired
+ private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
+
+ @Autowired
+ private AuthenticationException authenticationException;
+
+ @Autowired
+ private AccessDeniedHandExcetion accessDeniedHandExcetion;
+
+
+
+ @Override
+ protected void configure(HttpSecurity httpSecurity) throws Exception {
+ httpSecurity
+ // 关闭 CSRF
+ .csrf().disable()
+ //不通过Session获取SecurityContext
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ //对于登录接口,允许匿名访问
+ .authorizeRequests()
+ .antMatchers("/user/login").anonymous()
+ .antMatchers("/user/code").permitAll()
+ .antMatchers("/app/app-doctor/*").permitAll()//医生登录
+ .antMatchers("/app/app-user/*").permitAll() //家长登录
+ .and()
+ .authorizeRequests()
+ // 放行静态资源
+ .antMatchers(
+ HttpMethod.GET,
+ "/*.html",
+ "/**/*.html",
+ "/**/*.css",
+ "/**/*.js",
+ "/webSocket/**"
+ ).permitAll()
+ // 放行 swagger 文档
+ .antMatchers("/swagger-ui.html").permitAll()
+ .antMatchers("/swagger-resources/**").permitAll()
+ .antMatchers("/webjars/**").permitAll()
+ .antMatchers("/*/api-docs").permitAll()
+ // 放行 图片预览
+ .antMatchers("/report/**").permitAll()
+ .antMatchers("/images/**").permitAll()
+ .antMatchers("/pageimage/**").permitAll()
+ .antMatchers("/avatar/**").permitAll()
+ .antMatchers("/systemurl/**").permitAll()
+ .antMatchers("/api/imageserver/upload").permitAll()
+ .antMatchers("/activity/**").permitAll()
+ .antMatchers("/appnews/**").permitAll()
+ .antMatchers("/QRcode/**").permitAll()
+ .antMatchers("/template/**").permitAll()
+ .antMatchers("/tempword/**").permitAll()
+ .antMatchers("/tempzip/**").permitAll()
+
+ //测试放行所有访问
+ .antMatchers("/**/**").permitAll()
+ //除上面外的所有请求全部需要签权认证
+ .anyRequest().authenticated();
+
+ //允许跨域
+ httpSecurity.cors();
+
+ //将jwt过来器加入到httpSecurity过滤器链中
+ httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
+
+ //配置异常处理器
+ httpSecurity.exceptionHandling()
+ .authenticationEntryPoint(authenticationException)
+ .accessDeniedHandler(accessDeniedHandExcetion);
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/SwaggerConfig.java b/java/src/main/java/com/yfd/platform/config/SwaggerConfig.java
new file mode 100644
index 0000000..8b7e6df
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/SwaggerConfig.java
@@ -0,0 +1,79 @@
+package com.yfd.platform.config;
+
+import io.swagger.models.auth.In;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.builders.RequestParameterBuilder;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.service.RequestParameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * swagger配置
+ */
+@Configuration
+public class SwaggerConfig {
+
+ Boolean swaggerEnabled = true;
+
+ @Bean
+ public Docket createRestGBApi() {
+ return new Docket(DocumentationType.OAS_30)
+ .apiInfo(apiInfo())
+// .globalRequestParameters(generateRequestParameters())
+ .groupName("1. 系统管理")
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("com.yfd.platform.system.controller"))
+ .paths(PathSelectors.any())
+ .build()
+ .pathMapping("/")
+ .enable(swaggerEnabled);
+ }
+
+ @Bean
+ public Docket createRestStorageApi() {
+ return new Docket(DocumentationType.OAS_30)
+ .apiInfo(apiInfo())
+// .globalRequestParameters(generateRequestParameters())
+ .groupName("2. 文件存储管理")
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("com.yfd.platform.modules.storage.controller"))
+ .paths(PathSelectors.any())
+ .build()
+ .pathMapping("/")
+ .enable(swaggerEnabled);
+ }
+
+
+ /**
+ * 获取通用的全局参数
+ *
+ * @return 全局参数列表
+ */
+ private List generateRequestParameters(){
+ RequestParameterBuilder token = new RequestParameterBuilder();
+ List parameters = new ArrayList<>();
+ token.name("token").description("token").in(In.HEADER.toValue()).required(true).build();
+ parameters.add(token.build());
+ return parameters;
+ }
+
+
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ .title("项目API 接口文档")
+ .description("")
+ .contact(new Contact("郑顺利", "郑顺利", "13910913995@163.com"))
+ .version("3.0")
+ .build();
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/WebConfig.java b/java/src/main/java/com/yfd/platform/config/WebConfig.java
new file mode 100644
index 0000000..b3cb4bc
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/WebConfig.java
@@ -0,0 +1,86 @@
+package com.yfd.platform.config;
+
+import cn.hutool.cache.Cache;
+import cn.hutool.cache.CacheUtil;
+import lombok.SneakyThrows;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import javax.servlet.ServletContext;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+ @Value("${file-space.system}")
+ private String systempath;
+
+ private final ServletContext servletContext;
+
+ public WebConfig(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
+ @Bean
+ public Cache loginuserCache() {
+ return CacheUtil.newLRUCache(200);//用户登录缓存数 缺省200
+ }
+
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source =
+ new UrlBasedCorsConfigurationSource();
+ CorsConfiguration config = new CorsConfiguration();
+ config.setAllowCredentials(true);
+ config.addAllowedOriginPattern("*");
+ config.addAllowedHeader("*");
+ config.addAllowedMethod("*");
+ config.setMaxAge(3600L);
+ source.registerCorsConfiguration("/**", config);
+ return new CorsFilter(source);
+ }
+ private boolean isTomcatEnvironment() {
+ // 在此处可以根据不同的条件来判断当前运行环境
+ // 例如可以检查System.getProperty("catalina.home")是否存在
+ // 或者检查是否存在某个特定的系统属性来区分环境
+// return System.getProperty("catalina.home") != null;
+ return false;
+ }
+
+ @SneakyThrows
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ if (isTomcatEnvironment()) {
+ // Tomcat部署环境
+ String appRoot = servletContext.getRealPath("/");
+ String iconPath = appRoot + "WEB-INF/classes/static/icon/";
+
+ registry.addResourceHandler("/menu/**")
+ .addResourceLocations("file:" + iconPath)
+ .setCachePeriod(0);
+ } else {
+ // IDEA开发环境
+ registry.addResourceHandler("/menu/**")
+ .addResourceLocations("classpath:/static/icon/")
+ .setCachePeriod(0);
+ registry.addResourceHandler("swagger-ui.html").addResourceLocations(
+ "classpath:/META-INF/resources/");
+ }
+
+ String menuUrl = "file:" + systempath + "menu/";
+ registry.addResourceHandler("/menu/**").addResourceLocations(menuUrl).setCachePeriod(0);
+
+
+ String systemUrl = "file:" + systempath + "user/";
+ registry.addResourceHandler("/avatar/**").addResourceLocations(systemUrl).setCachePeriod(0);
+
+
+
+
+ }
+
+}
diff --git a/java/src/main/java/com/yfd/platform/config/WebSocketConfig.java b/java/src/main/java/com/yfd/platform/config/WebSocketConfig.java
new file mode 100644
index 0000000..349ead0
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/WebSocketConfig.java
@@ -0,0 +1,16 @@
+package com.yfd.platform.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+@Configuration
+public class WebSocketConfig {
+
+ @Bean
+ public ServerEndpointExporter serverEndpointExporter() {
+
+ return new ServerEndpointExporter();
+ }
+}
+
diff --git a/java/src/main/java/com/yfd/platform/config/bean/LoginCode.java b/java/src/main/java/com/yfd/platform/config/bean/LoginCode.java
new file mode 100644
index 0000000..2a7586b
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/bean/LoginCode.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config.bean;
+
+import lombok.Data;
+
+/**
+ * 登录验证码配置信息
+ *
+ * @author: liaojinlong
+ * @date: 2020/6/10 18:53
+ */
+@Data
+public class LoginCode {
+
+ /**
+ * 验证码配置
+ */
+ private LoginCodeEnum codeType;
+ /**
+ * 验证码有效期 分钟
+ */
+ private Long expiration = 2L;
+ /**
+ * 验证码内容长度
+ */
+ private int length = 2;
+ /**
+ * 验证码宽度
+ */
+ private int width = 111;
+ /**
+ * 验证码高度
+ */
+ private int height = 36;
+ /**
+ * 验证码字体
+ */
+ private String fontName;
+ /**
+ * 字体大小
+ */
+ private int fontSize = 25;
+
+ public LoginCodeEnum getCodeType() {
+ return codeType;
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/bean/LoginCodeEnum.java b/java/src/main/java/com/yfd/platform/config/bean/LoginCodeEnum.java
new file mode 100644
index 0000000..d9ade21
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/bean/LoginCodeEnum.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config.bean;
+
+/**
+ * 验证码配置枚举
+ *
+ * @author: liaojinlong
+ * @date: 2020/6/10 17:40
+ */
+
+public enum LoginCodeEnum {
+ /**
+ * 算数
+ */
+ arithmetic,
+ /**
+ * 中文
+ */
+ chinese,
+ /**
+ * 中文闪图
+ */
+ chinese_gif,
+ /**
+ * 闪图
+ */
+ gif,
+ spec
+}
diff --git a/java/src/main/java/com/yfd/platform/config/bean/LoginProperties.java b/java/src/main/java/com/yfd/platform/config/bean/LoginProperties.java
new file mode 100644
index 0000000..b16644d
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/bean/LoginProperties.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version loginCode.length.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-loginCode.length.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config.bean;
+
+import cn.hutool.core.util.StrUtil;
+import com.wf.captcha.*;
+import com.wf.captcha.base.Captcha;
+import com.yfd.platform.exception.BadConfigurationException;
+import lombok.Data;
+import java.awt.*;
+import java.util.Objects;
+
+/**
+ * 配置文件读取
+ *
+ * @author liaojinlong
+ * @date loginCode.length0loginCode.length0/6/10 17:loginCode.length6
+ */
+@Data
+public class LoginProperties {
+
+ /**
+ * 账号单用户 登录
+ */
+ private boolean singleLogin = false;
+
+ private LoginCode loginCode;
+ /**
+ * 用户登录信息缓存
+ */
+ private boolean cacheEnable;
+
+ public boolean isSingleLogin() {
+ return singleLogin;
+ }
+
+ public boolean isCacheEnable() {
+ return cacheEnable;
+ }
+
+ /**
+ * 获取验证码生产类
+ *
+ * @return /
+ */
+ public Captcha getCaptcha() {
+ if (Objects.isNull(loginCode)) {
+ loginCode = new LoginCode();
+ if (Objects.isNull(loginCode.getCodeType())) {
+ loginCode.setCodeType(LoginCodeEnum.arithmetic);
+ }
+ }
+ return switchCaptcha(loginCode);
+ }
+
+ /**
+ * 依据配置信息生产验证码
+ *
+ * @param loginCode 验证码配置信息
+ * @return /
+ */
+ private Captcha switchCaptcha(LoginCode loginCode) {
+ Captcha captcha;
+ synchronized (this) {
+ switch (loginCode.getCodeType()) {
+ case arithmetic:
+ // 算术类型 https://gitee.com/whvse/EasyCaptcha
+ captcha = new ArithmeticCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ // 几位数运算,默认是两位
+ captcha.setLen(loginCode.getLength());
+ break;
+ case chinese:
+ captcha = new ChineseCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ captcha.setLen(loginCode.getLength());
+ break;
+ case chinese_gif:
+ captcha = new ChineseGifCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ captcha.setLen(loginCode.getLength());
+ break;
+ case gif:
+ captcha = new GifCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ captcha.setLen(loginCode.getLength());
+ break;
+ case spec:
+ captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight());
+ captcha.setLen(loginCode.getLength());
+ break;
+ default:
+ throw new BadConfigurationException("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
+ }
+ }
+ if(StrUtil.isNotBlank(loginCode.getFontName())){
+ captcha.setFont(new Font(loginCode.getFontName(), Font.PLAIN, loginCode.getFontSize()));
+ }
+ return captcha;
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/thread/AsyncConfig.java b/java/src/main/java/com/yfd/platform/config/thread/AsyncConfig.java
new file mode 100644
index 0000000..c24fdfd
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/thread/AsyncConfig.java
@@ -0,0 +1,31 @@
+package com.yfd.platform.config.thread;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+
+ @Bean(name = "asyncExecutor")
+ public Executor asyncExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ // 核心线程数(处理器数量)
+ executor.setCorePoolSize(16);
+ // 最大线程数
+ executor.setMaxPoolSize(64);
+ // 队列容量
+ executor.setQueueCapacity(100);
+ // 线程名前缀
+ executor.setThreadNamePrefix("AsyncThread-");
+ // 线程池任务拒绝策略
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ executor.initialize();
+ return executor;
+ }
+}
\ No newline at end of file
diff --git a/java/src/main/java/com/yfd/platform/config/thread/AsyncTaskExecutePool.java b/java/src/main/java/com/yfd/platform/config/thread/AsyncTaskExecutePool.java
new file mode 100644
index 0000000..ff10654
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/thread/AsyncTaskExecutePool.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config.thread;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 异步任务线程池装配类
+ * @author https://juejin.im/entry/5abb8f6951882555677e9da2
+ * @date 2019年10月31日15:06:18
+ */
+@Slf4j
+@Configuration
+public class AsyncTaskExecutePool implements AsyncConfigurer {
+
+ /** 注入配置类 */
+ private final AsyncTaskProperties config;
+
+ public AsyncTaskExecutePool(AsyncTaskProperties config) {
+ this.config = config;
+ }
+
+ @Override
+ public Executor getAsyncExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ //核心线程池大小
+ executor.setCorePoolSize(config.getCorePoolSize());
+ //最大线程数
+ executor.setMaxPoolSize(config.getMaxPoolSize());
+ //队列容量
+ executor.setQueueCapacity(config.getQueueCapacity());
+ //活跃时间
+ executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
+ //线程名字前缀
+ executor.setThreadNamePrefix("el-async-");
+ // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
+ // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ executor.initialize();
+ return executor;
+ }
+
+ @Override
+ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+ return (throwable, method, objects) -> {
+ log.error("===="+throwable.getMessage()+"====", throwable);
+ log.error("exception method:"+method.getName());
+ };
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/thread/AsyncTaskProperties.java b/java/src/main/java/com/yfd/platform/config/thread/AsyncTaskProperties.java
new file mode 100644
index 0000000..a5bc7d2
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/thread/AsyncTaskProperties.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config.thread;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 线程池配置属性类
+ * @author https://juejin.im/entry/5abb8f6951882555677e9da2
+ * @date 2019年10月31日14:58:18
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "task.pool")
+public class AsyncTaskProperties {
+
+ private int corePoolSize;
+
+ private int maxPoolSize;
+
+ private int keepAliveSeconds;
+
+ private int queueCapacity;
+}
diff --git a/java/src/main/java/com/yfd/platform/config/thread/TheadFactoryName.java b/java/src/main/java/com/yfd/platform/config/thread/TheadFactoryName.java
new file mode 100644
index 0000000..b2bb8ff
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/thread/TheadFactoryName.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config.thread;
+
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 自定义线程名称
+ * @author
+ * @date 2019年10月31日17:49:55
+ */
+@Component
+public class TheadFactoryName implements ThreadFactory {
+
+ private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
+ private final ThreadGroup group;
+ private final AtomicInteger threadNumber = new AtomicInteger(1);
+ private final String namePrefix;
+
+ public TheadFactoryName() {
+ this("el-pool");
+ }
+
+ private TheadFactoryName(String name){
+ SecurityManager s = System.getSecurityManager();
+ group = (s != null) ? s.getThreadGroup() :
+ Thread.currentThread().getThreadGroup();
+ //此时namePrefix就是 name + 第几个用这个工厂创建线程池的
+ this.namePrefix = name +
+ POOL_NUMBER.getAndIncrement();
+ }
+
+ @Override
+ public Thread newThread(Runnable r) {
+ //此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程
+ Thread t = new Thread(group, r,
+ namePrefix + "-thread-"+threadNumber.getAndIncrement(),
+ 0);
+ if (t.isDaemon()) {
+ t.setDaemon(false);
+ }
+ if (t.getPriority() != Thread.NORM_PRIORITY) {
+ t.setPriority(Thread.NORM_PRIORITY);
+ }
+ return t;
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/config/thread/ThreadPoolExecutorUtil.java b/java/src/main/java/com/yfd/platform/config/thread/ThreadPoolExecutorUtil.java
new file mode 100644
index 0000000..cb84cc4
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/config/thread/ThreadPoolExecutorUtil.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yfd.platform.config.thread;
+
+
+
+import com.yfd.platform.utils.SpringContextHolder;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 用于获取自定义线程池
+ * @author
+ * @date 2019年10月31日18:16:47
+ */
+public class ThreadPoolExecutorUtil {
+
+ public static ThreadPoolExecutor getPoll(){
+ AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class);
+ return new ThreadPoolExecutor(
+ properties.getCorePoolSize(),
+ properties.getMaxPoolSize(),
+ properties.getKeepAliveSeconds(),
+ TimeUnit.SECONDS,
+ new ArrayBlockingQueue<>(properties.getQueueCapacity()),
+ new TheadFactoryName()
+ );
+ }
+}
diff --git a/java/src/main/java/com/yfd/platform/constant/Constant.java b/java/src/main/java/com/yfd/platform/constant/Constant.java
new file mode 100644
index 0000000..1539796
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/constant/Constant.java
@@ -0,0 +1,48 @@
+package com.yfd.platform.constant;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author LiMengNan
+ * @Date: 2023/3/3 17:40
+ * @Description: 常量类
+ */
+public class Constant {
+
+ public static final String LOGIN = "login:";
+ public static final String TOKEN = "token:";
+ public static final String USER_ID = "userid";
+ public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+ public static final String CODE_KEY = "code-key-";
+ public static final long CODE_EXPIRATION_TIME = 1000 * 60;
+ /**
+ * 用于IP定位转换
+ */
+ public static final String REGION = "内网IP|内网IP";
+ /**
+ * win 系统
+ */
+ public static final String WIN = "win";
+
+ /**
+ * mac 系统
+ */
+ public static final String MAC = "mac";
+
+ /**
+ * 常用接口
+ */
+ public static class Url {
+
+ // IP归属地查询
+ // public static final String IP_URL = "http://whois.pconline.com
+ // .cn/ipJson.jsp?ip=%s&json=true";
+ public static final String IP_URL = "http://whois.pconline.com" +
+ ".cn/ipJson.jsp?ip=%s&json=true";
+ }
+ public final static List GRADE_NAMES = Arrays.asList("小班", "中班", "大班", "大大班", "小学一年级", "小学二年级", "小学三年级", "小学四年级", "小学五年级", "小学六年级",
+ "初中一年级", "初中二年级", "初中三年级", "初中四年级",
+ "高中一年级", "高中二年级", "高中三年级", "高中四年级", "高中五年级", "高中六年级", "高中七年级");
+}
diff --git a/java/src/main/java/com/yfd/platform/constant/MdcConstant.java b/java/src/main/java/com/yfd/platform/constant/MdcConstant.java
new file mode 100644
index 0000000..8d49836
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/constant/MdcConstant.java
@@ -0,0 +1,16 @@
+package com.yfd.platform.constant;
+
+/**
+ * Slf4j mdc 常量
+ *
+ * @author zhengsl
+ */
+public class MdcConstant {
+
+ public static final String TRACE_ID = "traceId";
+
+ public static final String IP = "ip";
+
+ public static final String USER = "user";
+
+}
diff --git a/java/src/main/java/com/yfd/platform/constant/SystemConfigConstant.java b/java/src/main/java/com/yfd/platform/constant/SystemConfigConstant.java
new file mode 100644
index 0000000..e7466f9
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/constant/SystemConfigConstant.java
@@ -0,0 +1,13 @@
+package com.yfd.platform.constant;
+
+/**
+ * 系统设置字段常量.
+ *
+ * @author zhengsl
+ */
+public class SystemConfigConstant {
+
+ public static final String RSA_HEX_KEY = "rsaHexKey";
+
+
+}
diff --git a/java/src/main/java/com/yfd/platform/constant/ZFileConstant.java b/java/src/main/java/com/yfd/platform/constant/ZFileConstant.java
new file mode 100644
index 0000000..814af95
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/constant/ZFileConstant.java
@@ -0,0 +1,29 @@
+package com.yfd.platform.constant;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * ZFile 常量
+ *
+ * @author zhengsl
+ */
+@Configuration
+public class ZFileConstant {
+
+ public static final Character PATH_SEPARATOR_CHAR = '/';
+
+ public static final String PATH_SEPARATOR = "/";
+
+ /**
+ * 最大支持文本文件大小为 ? KB 的文件内容.
+ */
+ public static Long TEXT_MAX_FILE_SIZE_KB = 100L;
+
+ @Autowired(required = false)
+ public void setTextMaxFileSizeMb(@Value("${file-system.preview.text.maxFileSizeKb}") Long maxFileSizeKb) {
+ ZFileConstant.TEXT_MAX_FILE_SIZE_KB = maxFileSizeKb;
+ }
+
+}
diff --git a/java/src/main/java/com/yfd/platform/datasource/DataSource.java b/java/src/main/java/com/yfd/platform/datasource/DataSource.java
new file mode 100644
index 0000000..7c6d795
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/datasource/DataSource.java
@@ -0,0 +1,17 @@
+package com.yfd.platform.datasource;
+
+import java.lang.annotation.*;
+
+/******************************
+ * 用途说明:
+ * 作者姓名: wxy
+ * 创建时间: 2022/9/23 17:48
+ ******************************/
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataSource {
+
+ String name() default "";
+
+}
diff --git a/java/src/main/java/com/yfd/platform/datasource/DataSourceAspect.java b/java/src/main/java/com/yfd/platform/datasource/DataSourceAspect.java
new file mode 100644
index 0000000..f20c0f8
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/datasource/DataSourceAspect.java
@@ -0,0 +1,55 @@
+package com.yfd.platform.datasource;
+
+import cn.hutool.core.util.StrUtil;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+
+/******************************
+ * 用途说明:
+ * 作者姓名: wxy
+ * 创建时间: 2022/9/23 17:50
+ ******************************/
+@Aspect
+@Component
+public class DataSourceAspect {
+
+ @Pointcut("@annotation(com.yfd.platform.datasource.DataSource)")
+ public void dataSourcePointCut() {
+
+ }
+
+ private String DataBaseName;
+
+ @Around("dataSourcePointCut()")
+ public Object around(ProceedingJoinPoint point) throws Throwable {
+ MethodSignature signature = (MethodSignature) point.getSignature();
+ Method method = signature.getMethod();
+ if (StrUtil.isNotBlank(DataBaseName)){
+ DynamicDataSource.setDataSource(DataBaseName);
+ }else {
+ DynamicDataSource.setDataSource("master");
+ }
+
+ try {
+ return point.proceed();
+ } finally {
+ DynamicDataSource.clearDataSource();
+ }
+ }
+
+ public String getDataBase(Integer type){
+ if (type == 1){
+ DataBaseName="master";
+ }else {
+ DataBaseName="slave";
+ }
+ return DataBaseName;
+ }
+
+}
diff --git a/java/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java b/java/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java
new file mode 100644
index 0000000..8b52521
--- /dev/null
+++ b/java/src/main/java/com/yfd/platform/datasource/DynamicDataSource.java
@@ -0,0 +1,40 @@
+package com.yfd.platform.datasource;
+
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+import javax.sql.DataSource;
+import java.util.Map;
+
+/******************************
+ * 用途说明:
+ * 作者姓名: wxy
+ * 创建时间: 2022/9/23 17:47
+ ******************************/
+public class DynamicDataSource extends AbstractRoutingDataSource {
+ private static final ThreadLocal contextHolder = new ThreadLocal<>();
+
+ public DynamicDataSource(DataSource defaultTargetDataSource, Map