woody пре 1 година
родитељ
комит
2a248cdc3f

+ 35 - 0
framework-base/src/main/java/com/chelvc/framework/base/config/MultiserverMvcConfigurer.java

@@ -0,0 +1,35 @@
+package com.chelvc.framework.base.config;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+
+import com.chelvc.framework.base.context.ApplicationContextHolder;
+import com.chelvc.framework.common.util.StringUtils;
+import com.google.common.collect.Maps;
+import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
+import org.springframework.core.io.Resource;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+/**
+ * 多服务MVC配置
+ *
+ * @author Woody
+ * @date 2024/1/30
+ */
+public class MultiserverMvcConfigurer implements WebMvcRegistrations {
+    @Override
+    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
+        List<Resource> resources = ApplicationContextHolder.getApplicationResources();
+        Map<String, Predicate<Class<?>>> prefixes = Maps.newHashMapWithExpectedSize(resources.size());
+        for (Resource resource : resources) {
+            String prefix = ApplicationContextHolder.getResourcePrefix(resource);
+            if (StringUtils.notEmpty(prefix)) {
+                prefixes.put(prefix, clazz -> ApplicationContextHolder.isResourceClass(resource, clazz));
+            }
+        }
+        RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
+        mapping.setPathPrefixes(prefixes);
+        return mapping;
+    }
+}

+ 42 - 0
framework-base/src/main/java/com/chelvc/framework/base/context/ApplicationContextHolder.java

@@ -3,6 +3,7 @@ package com.chelvc.framework.base.context;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
@@ -578,6 +579,47 @@ public class ApplicationContextHolder implements ApplicationContextAware {
         return properties.getProperty(APPLICATION_NAME_PROPERTY);
     }
 
+    /**
+     * 获取资源前缀
+     *
+     * @param resource 资源对象
+     * @return 资源前缀标识
+     */
+    public static String getResourcePrefix(@NonNull Resource resource) {
+        String application = getApplicationName(resource);
+        return StringUtils.isEmpty(application) ? application : application.replace('.', '/');
+    }
+
+    /**
+     * 判断类对象是否属于指定资源
+     *
+     * @param resource 资源对象
+     * @param clazz    类对象
+     * @return true/false
+     */
+    public static boolean isResourceClass(@NonNull Resource resource, @NonNull Class<?> clazz) {
+        String file = clazz.getProtectionDomain().getCodeSource().getLocation().getPath();
+        try {
+            return resource.getURL().getPath().contains(file);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 查找类对象所属资源
+     *
+     * @param clazz     类对象
+     * @param resources 资源对象集合
+     * @return 资源对象
+     */
+    public static Resource lookupClassResource(@NonNull Class<?> clazz, @NonNull Collection<Resource> resources) {
+        if (ObjectUtils.isEmpty(resources)) {
+            return null;
+        }
+        return resources.stream().filter(resource -> isResourceClass(resource, clazz)).findAny().orElse(null);
+    }
+
     /**
      * 查找应用中的类对象
      *

+ 12 - 27
framework-base/src/main/java/com/chelvc/framework/base/context/SessionContextHolder.java

@@ -184,22 +184,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 用户ID
      */
     public static Long getId() {
-        return getId(true);
-    }
-
-    /**
-     * 获取当前用户ID
-     *
-     * @param required 是否必须
-     * @return 用户ID
-     */
-    public static Long getId(boolean required) {
-        Session session = getSession(required);
-        Long id = ObjectUtils.ifNull(session, Session::getId);
-        if (required) {
-            return AssertUtils.nonnull(id, () -> "Session id must not be null");
-        }
-        return id;
+        return ObjectUtils.ifNull(getSession(false), Session::getId);
     }
 
     /**
@@ -218,7 +203,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 请求地址
      */
     public static String getHost() {
-        return ObjectUtils.ifNull(getSession(), Session::getHost);
+        return ObjectUtils.ifNull(getSession(false), Session::getHost);
     }
 
     /**
@@ -237,7 +222,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 使用信息
      */
     public static Using getUsing() {
-        return ObjectUtils.ifNull(getSession(), Session::getUsing);
+        return ObjectUtils.ifNull(getSession(false), Session::getUsing);
     }
 
     /**
@@ -256,7 +241,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 应用范围
      */
     public static String getScope() {
-        return ObjectUtils.ifNull(getSession(), Session::getScope);
+        return ObjectUtils.ifNull(getSession(false), Session::getScope);
     }
 
     /**
@@ -275,7 +260,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 设备标识
      */
     public static String getDevice() {
-        return ObjectUtils.ifNull(getSession(), Session::getDevice);
+        return ObjectUtils.ifNull(getSession(false), Session::getDevice);
     }
 
     /**
@@ -294,7 +279,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 渠道来源
      */
     public static String getChannel() {
-        return ObjectUtils.ifNull(getSession(), Session::getChannel);
+        return ObjectUtils.ifNull(getSession(false), Session::getChannel);
     }
 
     /**
@@ -313,7 +298,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 平台信息
      */
     public static Platform getPlatform() {
-        return ObjectUtils.ifNull(getSession(), Session::getPlatform);
+        return ObjectUtils.ifNull(getSession(false), Session::getPlatform);
     }
 
     /**
@@ -332,7 +317,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 终端信息
      */
     public static Terminal getTerminal() {
-        return ObjectUtils.ifNull(getSession(), Session::getTerminal);
+        return ObjectUtils.ifNull(getSession(false), Session::getTerminal);
     }
 
     /**
@@ -351,7 +336,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 版本信息
      */
     public static String getVersion() {
-        return ObjectUtils.ifNull(getSession(), Session::getVersion);
+        return ObjectUtils.ifNull(getSession(false), Session::getVersion);
     }
 
     /**
@@ -370,7 +355,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return true/false
      */
     public static boolean isAnonymous() {
-        Session session = getSession();
+        Session session = getSession(false);
         return session == null || session.isAnonymous();
     }
 
@@ -391,7 +376,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 时间戳
      */
     public static Long getTimestamp() {
-        return ObjectUtils.ifNull(getSession(), Session::getTimestamp);
+        return ObjectUtils.ifNull(getSession(false), Session::getTimestamp);
     }
 
     /**
@@ -429,7 +414,7 @@ public class SessionContextHolder implements ServletRequestListener {
      * @return 设备指纹
      */
     public static String getFingerprint() {
-        return ObjectUtils.ifNull(getSession(), Session::getFingerprint);
+        return ObjectUtils.ifNull(getSession(false), Session::getFingerprint);
     }
 
     /**

+ 1 - 1
framework-database/src/main/java/com/chelvc/framework/database/context/DatabaseContextHolder.java

@@ -577,7 +577,7 @@ public final class DatabaseContextHolder {
      */
     public static void initializeEntityDefaultValues(@NonNull Entity<?> entity) {
         // 设置新增属性默认值
-        Long operator = SessionContextHolder.getId(false);
+        Long operator = SessionContextHolder.getId();
         if (operator != null && entity instanceof Creatable) {
             Creatable<?> creatable = (Creatable<?>) entity;
             if (creatable.getCreator() == null) {

+ 6 - 11
framework-location/src/main/java/com/chelvc/framework/location/config/LocationConfigurer.java

@@ -11,7 +11,6 @@ import com.chelvc.framework.location.support.JuheLocationHandler;
 import com.chelvc.framework.location.support.TencentLocationHandler;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.client.RestTemplate;
@@ -45,20 +44,16 @@ public class LocationConfigurer {
     }
 
     @Bean
-    @ConditionalOnProperty(prefix = "location.caching", name = "enabled", havingValue = "false")
     public LocationHandler locationHandler() {
         List<LocationHandler> handlers = this.properties.getClients().stream().map(this::initializeLocationHandler)
                 .collect(Collectors.toList());
-        return ObjectUtils.isEmpty(handlers) ? null : new DelegatingLocationHandler(handlers);
-    }
-
-    @Bean
-    @ConditionalOnProperty(prefix = "location.caching", name = "enabled", havingValue = "true")
-    public LocationHandler cacheableLocationHandler() {
-        LocationHandler handler = this.locationHandler();
-        if (handler == null) {
+        if (ObjectUtils.isEmpty(handlers)) {
             return null;
         }
-        return new CacheableLocationHandler(handler, this.properties.getCaching().getExpiration());
+        LocationHandler delegating = new DelegatingLocationHandler(handlers);
+        if (this.properties.getCaching().isEnabled()) {
+            return new CacheableLocationHandler(delegating, this.properties.getCaching().getExpiration());
+        }
+        return delegating;
     }
 }

+ 24 - 1
framework-oauth/src/main/java/com/chelvc/framework/oauth/config/OauthConfigurer.java

@@ -2,6 +2,7 @@ package com.chelvc.framework.oauth.config;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -9,8 +10,11 @@ import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 
 import com.beust.jcommander.internal.Sets;
+import com.chelvc.framework.base.config.MultiserverMvcConfigurer;
+import com.chelvc.framework.base.context.ApplicationContextHolder;
 import com.chelvc.framework.base.context.LoggingContextHolder;
 import com.chelvc.framework.base.context.SessionContextHolder;
+import com.chelvc.framework.base.util.HttpUtils;
 import com.chelvc.framework.base.util.SpringUtils;
 import com.chelvc.framework.common.model.Result;
 import com.chelvc.framework.common.util.AESUtils;
@@ -26,6 +30,7 @@ import org.springframework.aop.framework.AopProxyUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
+import org.springframework.core.io.Resource;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.authentication.AuthenticationManager;
@@ -145,8 +150,24 @@ public class OAuthConfigurer extends WebSecurityConfigurerAdapter {
         if (ObjectUtils.notEmpty(this.properties.getIgnores())) {
             ignores.addAll(this.properties.getIgnores());
         }
+
+        // 判断是否启用多服务MVC配置,如果包含则获取所有服务资源对象
+        boolean multiserver = this.applicationContext.containsBean(MultiserverMvcConfigurer.class.getName());
+        List<Resource> resources = multiserver ?
+                ApplicationContextHolder.getApplicationResources() : Collections.emptyList();
+
+        // 将所有使用@Authorize注解并且enabled = true的接口地址排除认证
         SpringUtils.lookupControllers(this.applicationContext).forEach(controller -> {
             Class<?> clazz = AopProxyUtils.ultimateTargetClass(controller);
+
+            // 如果启用多服务MVC配置则将服务名作为接口地址前缀
+            String prefix = null;
+            if (multiserver) {
+                Resource resource = ApplicationContextHolder.lookupClassResource(clazz, resources);
+                prefix = ObjectUtils.ifNull(resource, ApplicationContextHolder::getResourcePrefix);
+            }
+
+            // 遍历所有接口方法
             for (Method method : clazz.getDeclaredMethods()) {
                 int modifiers = method.getModifiers();
                 if (Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
@@ -155,7 +176,9 @@ public class OAuthConfigurer extends WebSecurityConfigurerAdapter {
                 Authorize authorize = method.getAnnotation(Authorize.class);
                 if ((authorize != null || (authorize = clazz.getAnnotation(Authorize.class)) != null)
                         && !authorize.enabled()) {
-                    ignores.addAll(SpringUtils.getApis(method));
+                    for (String api : SpringUtils.getApis(method)) {
+                        ignores.add(HttpUtils.uri(prefix, api));
+                    }
                 }
             }
         });

+ 0 - 7
framework-sms/src/main/java/com/chelvc/framework/sms/TemplateSmsHandler.java

@@ -9,13 +9,6 @@ import java.util.Map;
  * @date 2024/1/30
  */
 public interface TemplateSmsHandler {
-    /**
-     * 发送短信验证码
-     *
-     * @param captcha 验证码
-     */
-    void send(Captcha captcha);
-
     /**
      * 发送短信验证码
      *

+ 5 - 5
framework-sms/src/main/java/com/chelvc/framework/sms/config/SmsProperties.java

@@ -62,11 +62,6 @@ public class SmsProperties {
          */
         private String region;
 
-        /**
-         * 验证码模版
-         */
-        private String template;
-
         /**
          * 短信签名
          */
@@ -83,6 +78,11 @@ public class SmsProperties {
      */
     @Data
     public static class Captcha {
+        /**
+         * 验证码模版
+         */
+        private String template;
+
         /**
          * 验证码长度
          */

+ 0 - 7
framework-sms/src/main/java/com/chelvc/framework/sms/support/AliyunSmsHandler.java

@@ -26,7 +26,6 @@ import lombok.extern.slf4j.Slf4j;
 @Slf4j
 public class AliyunSmsHandler implements TemplateSmsHandler {
     private final Client client;
-    private final String template;
     private final String signature;
 
     public AliyunSmsHandler(@NonNull SmsProperties.Client properties) {
@@ -39,15 +38,9 @@ public class AliyunSmsHandler implements TemplateSmsHandler {
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
-        this.template = properties.getTemplate();
         this.signature = properties.getSignature();
     }
 
-    @Override
-    public void send(@NonNull Captcha captcha) {
-        this.send(this.template, captcha);
-    }
-
     @Override
     public void send(@NonNull String template, @NonNull Captcha captcha) {
         this.send(captcha.getMobile(), template, ImmutableMap.of("code", captcha.getCode()));

+ 1 - 1
framework-sms/src/main/java/com/chelvc/framework/sms/support/DefaultCaptchaSmsHandler.java

@@ -94,7 +94,7 @@ public class DefaultCaptchaSmsHandler implements CaptchaSmsHandler {
             String code = whitelisted ? mobile.substring(mobile.length() - length) : this.random(length);
             Captcha captcha = Captcha.builder().token(token).code(code).mobile(mobile).build();
             if (!whitelisted) {
-                Objects.requireNonNull(this.handler).send(captcha);
+                Objects.requireNonNull(this.handler).send(this.properties.getTemplate(), captcha);
             }
             RedisContextHolder.getDefaultTemplate().opsForValue()
                     .set(key, captcha, this.properties.getExpiration(), TimeUnit.SECONDS);

+ 0 - 5
framework-sms/src/main/java/com/chelvc/framework/sms/support/DelegatingTemplateSmsHandler.java

@@ -50,11 +50,6 @@ public class DelegatingTemplateSmsHandler implements TemplateSmsHandler {
         }
     }
 
-    @Override
-    public void send(@NonNull Captcha captcha) {
-        this.execute(handler -> handler.send(captcha));
-    }
-
     @Override
     public void send(@NonNull String template, @NonNull Captcha captcha) {
         this.execute(handler -> handler.send(template, captcha));

+ 0 - 7
framework-sms/src/main/java/com/chelvc/framework/sms/support/TencentSmsHandler.java

@@ -22,22 +22,15 @@ import lombok.extern.slf4j.Slf4j;
 public class TencentSmsHandler implements TemplateSmsHandler {
     private final SmsSingleSender sender;
     private final String region;
-    private final String template;
     private final String signature;
 
     public TencentSmsHandler(@NonNull SmsProperties.Client properties) {
         int appid = Integer.parseInt(properties.getId());
         this.sender = new SmsSingleSender(appid, properties.getSecret(), new PoolingHTTPClient());
         this.region = properties.getRegion();
-        this.template = properties.getTemplate();
         this.signature = properties.getSignature();
     }
 
-    @Override
-    public void send(@NonNull Captcha captcha) {
-        this.send(this.template, captcha);
-    }
-
     @Override
     public void send(@NonNull String template, @NonNull Captcha captcha) {
         this.send(captcha.getMobile(), template, captcha.getCode());