woody преди 1 година
родител
ревизия
2b3adc58eb

+ 1 - 1
framework-database/src/main/java/com/chelvc/framework/database/config/DatabaseConfigurer.java

@@ -74,7 +74,7 @@ public class DatabaseConfigurer {
     }
 
     @Bean
-    @ConditionalOnClass(RedisContextHolder.class)
+    @ConditionalOnClass(name = "com.chelvc.framework.redis.context.RedisContextHolder")
     public IdentifierGenerator identifierGenerator() {
         return entity -> RedisContextHolder.identity();
     }

+ 8 - 0
framework-database/src/main/java/com/chelvc/framework/database/mapper/BasicMapper.java

@@ -16,4 +16,12 @@ public interface BasicMapper<T> extends BaseMapper<T> {
      * @return true/false
      */
     boolean insertIgnore(T entity);
+
+    /**
+     * 创建或修改实体
+     *
+     * @param entity 实体对象实例
+     * @return true/false
+     */
+    boolean insertUpdate(T entity);
 }

+ 1 - 0
framework-database/src/main/java/com/chelvc/framework/database/mapper/CustomerSqlInjector.java

@@ -16,6 +16,7 @@ public class CustomerSqlInjector extends DefaultSqlInjector {
     public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
         List<AbstractMethod> methods = super.getMethodList(mapperClass);
         methods.add(new InsertIgnoreMethod());
+        methods.add(new InsertUpdateMethod());
         return methods;
     }
 }

+ 63 - 0
framework-database/src/main/java/com/chelvc/framework/database/mapper/InsertUpdateMethod.java

@@ -0,0 +1,63 @@
+package com.chelvc.framework.database.mapper;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.core.enums.SqlMethod;
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.chelvc.framework.common.util.StringUtils;
+import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
+import org.apache.ibatis.executor.keygen.KeyGenerator;
+import org.apache.ibatis.executor.keygen.NoKeyGenerator;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+
+/**
+ * 插入或修改方法实现
+ *
+ * @author Woody
+ * @date 2024/2/27
+ */
+public class InsertUpdateMethod extends AbstractMethod {
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        String keyColumn = null;
+        String keyProperty = null;
+        KeyGenerator keyGenerator;
+        if (StringUtils.isEmpty(tableInfo.getKeyProperty())) {
+            keyGenerator = new NoKeyGenerator();
+        } else if (tableInfo.getIdType() == IdType.AUTO) {
+            keyColumn = tableInfo.getKeyColumn();
+            keyProperty = tableInfo.getKeyProperty();
+            keyGenerator = new Jdbc3KeyGenerator();
+        } else if (tableInfo.getKeySequence() != null) {
+            keyColumn = tableInfo.getKeyColumn();
+            keyProperty = tableInfo.getKeyProperty();
+            String method = this.getMethod(SqlMethod.INSERT_ONE);
+            keyGenerator = TableInfoHelper.genKeyGenerator(method, tableInfo, this.builderAssistant);
+        } else {
+            keyGenerator = new NoKeyGenerator();
+        }
+        List<TableFieldInfo> fields = tableInfo.getFieldList();
+        String columns = tableInfo.getKeyInsertSqlColumn(false) +
+                this.filterTableFieldInfo(fields, null, TableFieldInfo::getInsertSqlColumn, EMPTY);
+        columns = columns.substring(0, columns.length() - 1);
+        String properties = tableInfo.getKeyInsertSqlProperty(null, false) +
+                this.filterTableFieldInfo(fields, null, i -> i.getInsertSqlProperty(null), EMPTY);
+        properties = properties.substring(0, properties.length() - 1);
+        String updates = this.filterTableFieldInfo(fields, null,
+                field -> field.getColumn() + " = values(" + field.getColumn() + ")", StringPool.COMMA);
+        String script = String.format(
+                "<script>\nINSERT IGNORE INTO %s (%s) VALUES (%s)\n ON DUPLICATE KEY UPDATE %s\n</script>",
+                tableInfo.getTableName(), columns, properties, updates
+        );
+        SqlSource source = this.languageDriver.createSqlSource(this.configuration, script, modelClass);
+        return this.addInsertMappedStatement(
+                mapperClass, modelClass, "insertUpdate", source, keyGenerator, keyProperty, keyColumn
+        );
+    }
+}

+ 30 - 4
framework-oauth/src/main/java/com/chelvc/framework/oauth/config/OauthConfigurer.java

@@ -44,8 +44,10 @@ import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
 import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
+import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtDecoder;
+import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
 import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
 import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
 import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
@@ -76,12 +78,36 @@ public class OAuthConfigurer extends WebSecurityConfigurerAdapter {
         SecretKey key = new SecretKeySpec(secret.getBytes(), AESUtils.ALGORITHM);
         NimbusJwtDecoder decoder = NimbusJwtDecoder.withSecretKey(key).build();
 
-        // 加载自定义JWT验
+        // 加JWT过期校验器
         List<OAuth2TokenValidator<Jwt>> validators = Lists.newLinkedList();
+        validators.add(new OAuth2TokenValidator<Jwt>() {
+            private final JwtTimestampValidator delegate = new JwtTimestampValidator();
+
+            @Override
+            public OAuth2TokenValidatorResult validate(Jwt jwt) {
+                OAuth2TokenValidatorResult result = this.delegate.validate(jwt);
+                if (result != null && result.hasErrors()) {
+                    throw new OAuth2AuthenticationException(new OAuth2Error(
+                            "TOKEN_EXPIRED", "Token has expired", null
+                    ));
+                }
+                return result;
+            }
+        });
+
+        // 加载自定义JWT验证器
         validators.addAll(this.applicationContext.getBeansOfType(TokenActiveValidator.class).values());
-        if (ObjectUtils.notEmpty(validators)) {
-            decoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(validators));
-        }
+
+        // 添加令牌会话初始化拦截器
+        validators.add(jwt -> {
+            SessionContextHolder.initializeSession(
+                    OAuthContextHolder.getId(jwt),
+                    OAuthContextHolder.getScope(jwt),
+                    OAuthContextHolder.isAnonymous(jwt)
+            );
+            return OAuth2TokenValidatorResult.success();
+        });
+        decoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(validators));
         return decoder;
     }
 

+ 0 - 16
framework-oauth/src/main/java/com/chelvc/framework/oauth/token/RedisTokenActiveValidator.java

@@ -2,7 +2,6 @@ package com.chelvc.framework.oauth.token;
 
 import java.util.Objects;
 
-import com.chelvc.framework.base.context.SessionContextHolder;
 import com.chelvc.framework.common.util.StringUtils;
 import com.chelvc.framework.oauth.context.OAuthContextHolder;
 import com.chelvc.framework.redis.context.RedisContextHolder;
@@ -11,7 +10,6 @@ import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.core.OAuth2Error;
 import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
 import org.springframework.security.oauth2.jwt.Jwt;
-import org.springframework.security.oauth2.jwt.JwtTimestampValidator;
 import org.springframework.stereotype.Component;
 
 /**
@@ -23,17 +21,8 @@ import org.springframework.stereotype.Component;
 @Component
 @ConditionalOnClass(RedisContextHolder.class)
 public class RedisTokenActiveValidator implements TokenActiveValidator {
-    private final JwtTimestampValidator timestampValidator = new JwtTimestampValidator();
-
     @Override
     public OAuth2TokenValidatorResult validate(Jwt jwt) {
-        // 校验令牌是否过期
-        OAuth2TokenValidatorResult result = this.timestampValidator.validate(jwt);
-        if (result != null && result.hasErrors()) {
-            throw new OAuth2AuthenticationException(new OAuth2Error("TOKEN_EXPIRED", "Token has expired", null));
-        }
-
-        // 获取并校验令牌有效性
         String key = OAuthContextHolder.key(OAuthContextHolder.getId(jwt));
         String token = (String) RedisContextHolder.getDefaultTemplate().opsForValue().get(key);
         if (StringUtils.isEmpty(token)) {
@@ -42,11 +31,6 @@ public class RedisTokenActiveValidator implements TokenActiveValidator {
             // 判断令牌是否相同,如果不相同则标识令牌已经被重置(账号已在其他地方登录)
             throw new OAuth2AuthenticationException(new OAuth2Error("TOKEN_REPLACED", "Token has replaced", null));
         }
-
-        // 初始化会话信息
-        SessionContextHolder.initializeSession(
-                OAuthContextHolder.getId(jwt), OAuthContextHolder.getScope(jwt), OAuthContextHolder.isAnonymous(jwt)
-        );
         return OAuth2TokenValidatorResult.success();
     }
 }