mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 12:39:05 +08:00
🎨 改进结构和代码格式. add spring-javaformat plugin and format all code
This commit is contained in:
1 parent
5414983f3d
commit
bd47066299
651 files changed
+13034
-12462
No files matched your search
@@ -19,15 +19,13 @@
|
||||
|
||||
package com.pig4cloud.pigx.auth;
|
||||
|
||||
|
||||
import com.pig4cloud.pigx.common.feign.annotation.EnablePigxFeignClients;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.cloud.client.SpringCloudApplication;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2020-02-08
|
||||
* 认证授权中心
|
||||
* @date 2020-02-08 认证授权中心
|
||||
*/
|
||||
@SpringCloudApplication
|
||||
@EnablePigxFeignClients
|
||||
@@ -36,4 +34,5 @@ public class PigxAuthApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(PigxAuthApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
+11
-14
@@ -45,17 +45,21 @@ import org.springframework.security.oauth2.provider.token.store.redis.RedisToken
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/6/22
|
||||
* 认证服务器配置
|
||||
* @date 2018/6/22 认证服务器配置
|
||||
*/
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
@EnableAuthorizationServer
|
||||
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
|
||||
|
||||
private final ClientDetailsService pigxClientDetailsServiceImpl;
|
||||
|
||||
private final AuthenticationManager authenticationManagerBean;
|
||||
|
||||
private final RedisConnectionFactory redisConnectionFactory;
|
||||
|
||||
private final UserDetailsService pigxUserDetailsService;
|
||||
|
||||
private final TokenEnhancer pigxTokenEnhancer;
|
||||
|
||||
@Override
|
||||
@@ -66,25 +70,18 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
|
||||
@Override
|
||||
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
|
||||
oauthServer
|
||||
.allowFormAuthenticationForClients()
|
||||
.checkTokenAccess("isAuthenticated()");
|
||||
oauthServer.allowFormAuthenticationForClients().checkTokenAccess("isAuthenticated()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
|
||||
endpoints
|
||||
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
|
||||
.tokenStore(tokenStore())
|
||||
.tokenEnhancer(pigxTokenEnhancer)
|
||||
.userDetailsService(pigxUserDetailsService)
|
||||
.authenticationManager(authenticationManagerBean)
|
||||
.reuseRefreshTokens(false)
|
||||
endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST).tokenStore(tokenStore())
|
||||
.tokenEnhancer(pigxTokenEnhancer).userDetailsService(pigxUserDetailsService)
|
||||
.authenticationManager(authenticationManagerBean).reuseRefreshTokens(false)
|
||||
.pathMapping("/oauth/confirm_access", "/token/confirm_access")
|
||||
.exceptionTranslator(new PigxWebResponseExceptionTranslator());
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public TokenStore tokenStore() {
|
||||
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
|
||||
@@ -97,5 +94,5 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
|
||||
});
|
||||
return tokenStore;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,43 +39,28 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHand
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/6/22
|
||||
* 认证相关配置
|
||||
* @date 2018/6/22 认证相关配置
|
||||
*/
|
||||
@Primary
|
||||
@Order(90)
|
||||
@Configuration
|
||||
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
protected void configure(HttpSecurity http) {
|
||||
http
|
||||
.formLogin()
|
||||
.loginPage("/token/login")
|
||||
.loginProcessingUrl("/token/form")
|
||||
.failureHandler(authenticationFailureHandler())
|
||||
.and()
|
||||
.logout()
|
||||
http.formLogin().loginPage("/token/login").loginProcessingUrl("/token/form")
|
||||
.failureHandler(authenticationFailureHandler()).and().logout()
|
||||
.logoutSuccessHandler((request, response, authentication) -> {
|
||||
String referer = request.getHeader(HttpHeaders.REFERER);
|
||||
response.sendRedirect(referer);
|
||||
})
|
||||
.deleteCookies("JSESSIONID")
|
||||
.invalidateHttpSession(true)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers(
|
||||
"/token/**",
|
||||
"/actuator/**",
|
||||
"/mobile/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and().csrf().disable()
|
||||
.apply(mobileSecurityConfigurer());
|
||||
}).deleteCookies("JSESSIONID").invalidateHttpSession(true).and().authorizeRequests()
|
||||
.antMatchers("/token/**", "/actuator/**", "/mobile/**").permitAll().anyRequest().authenticated().and()
|
||||
.csrf().disable().apply(mobileSecurityConfigurer());
|
||||
}
|
||||
|
||||
/**
|
||||
* 不拦截静态资源
|
||||
*
|
||||
* @param web
|
||||
*/
|
||||
@Override
|
||||
@@ -105,11 +90,9 @@ public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
|
||||
return new MobileSecurityConfigurer();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-updated
|
||||
* Encoded password does not look like BCrypt
|
||||
*
|
||||
* @return PasswordEncoder
|
||||
*/
|
||||
@Bean
|
||||
|
||||
@@ -59,25 +59,29 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/6/24
|
||||
* 删除token端点
|
||||
* @date 2018/6/24 删除token端点
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@RequestMapping("/token")
|
||||
public class PigxTokenEndpoint {
|
||||
private static final String PIGX_OAUTH_ACCESS = SecurityConstants.PIGX_PREFIX + SecurityConstants.OAUTH_PREFIX + "auth_to_access:";
|
||||
|
||||
private static final String PIGX_OAUTH_ACCESS = SecurityConstants.PIGX_PREFIX + SecurityConstants.OAUTH_PREFIX
|
||||
+ "auth_to_access:";
|
||||
|
||||
private final ClientDetailsService clientDetailsService;
|
||||
|
||||
private final RedisTemplate redisTemplate;
|
||||
|
||||
private final TokenStore tokenStore;
|
||||
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* 认证页面
|
||||
*
|
||||
* @param modelAndView
|
||||
* @param error 表单登录失败处理回调的错误信息
|
||||
* @param error 表单登录失败处理回调的错误信息
|
||||
* @return ModelAndView
|
||||
*/
|
||||
@GetMapping("/login")
|
||||
@@ -89,7 +93,6 @@ public class PigxTokenEndpoint {
|
||||
|
||||
/**
|
||||
* 确认授权页面
|
||||
*
|
||||
* @param request
|
||||
* @param session
|
||||
* @param modelAndView
|
||||
@@ -114,7 +117,6 @@ public class PigxTokenEndpoint {
|
||||
|
||||
/**
|
||||
* 退出token
|
||||
*
|
||||
* @param authHeader Authorization
|
||||
*/
|
||||
@DeleteMapping("/logout")
|
||||
@@ -129,7 +131,6 @@ public class PigxTokenEndpoint {
|
||||
|
||||
/**
|
||||
* 令牌管理调用
|
||||
*
|
||||
* @param token token
|
||||
* @return
|
||||
*/
|
||||
@@ -143,8 +144,7 @@ public class PigxTokenEndpoint {
|
||||
|
||||
OAuth2Authentication auth2Authentication = tokenStore.readAuthentication(accessToken);
|
||||
// 清空用户信息
|
||||
cacheManager.getCache(CacheConstants.USER_DETAILS)
|
||||
.evict(auth2Authentication.getName());
|
||||
cacheManager.getCache(CacheConstants.USER_DETAILS).evict(auth2Authentication.getName());
|
||||
|
||||
// 清空access token
|
||||
tokenStore.removeAccessToken(accessToken);
|
||||
@@ -155,35 +155,33 @@ public class PigxTokenEndpoint {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询token
|
||||
*
|
||||
* @param params 分页参数
|
||||
* @return
|
||||
*/
|
||||
@Inner
|
||||
@PostMapping("/page")
|
||||
public R<Page> tokenList(@RequestBody Map<String, Object> params) {
|
||||
//根据分页参数获取对应数据
|
||||
// 根据分页参数获取对应数据
|
||||
String key = String.format("%s*:%s", PIGX_OAUTH_ACCESS, TenantContextHolder.getTenantId());
|
||||
List<String> pages = findKeysForPage(key, MapUtil.getInt(params, PaginationConstants.CURRENT)
|
||||
, MapUtil.getInt(params, PaginationConstants.SIZE));
|
||||
List<String> pages = findKeysForPage(key, MapUtil.getInt(params, PaginationConstants.CURRENT),
|
||||
MapUtil.getInt(params, PaginationConstants.SIZE));
|
||||
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
|
||||
Page result = new Page(MapUtil.getInt(params, PaginationConstants.CURRENT), MapUtil.getInt(params, PaginationConstants.SIZE));
|
||||
Page result = new Page(MapUtil.getInt(params, PaginationConstants.CURRENT),
|
||||
MapUtil.getInt(params, PaginationConstants.SIZE));
|
||||
result.setRecords(redisTemplate.opsForValue().multiGet(pages));
|
||||
result.setTotal(redisTemplate.keys(key).size());
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
|
||||
private List<String> findKeysForPage(String patternKey, int pageNum, int pageSize) {
|
||||
ScanOptions options = ScanOptions.scanOptions().count(1000L)
|
||||
.match(patternKey).build();
|
||||
ScanOptions options = ScanOptions.scanOptions().count(1000L).match(patternKey).build();
|
||||
RedisSerializer<String> redisSerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
|
||||
Cursor cursor = (Cursor) redisTemplate.executeWithStickyConnection(redisConnection -> new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize));
|
||||
Cursor cursor = (Cursor) redisTemplate.executeWithStickyConnection(
|
||||
redisConnection -> new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize));
|
||||
List<String> result = new ArrayList<>();
|
||||
int tmpIndex = 0;
|
||||
int startIndex = (pageNum - 1) * pageSize;
|
||||
@@ -205,9 +203,11 @@ public class PigxTokenEndpoint {
|
||||
|
||||
try {
|
||||
cursor.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
log.error("关闭cursor 失败");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
+7
-5
@@ -44,21 +44,22 @@ import javax.servlet.http.HttpServletResponse;
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class PigxAuthenticationFailureEventHandler implements AuthenticationFailureHandler {
|
||||
|
||||
private final RemoteLogService logService;
|
||||
|
||||
/**
|
||||
* 异步处理,登录失败方法
|
||||
* <p>
|
||||
*
|
||||
* @param authenticationException 登录的authentication 对象
|
||||
* @param authentication 登录的authenticationException 对象
|
||||
* @param request 请求
|
||||
* @param response 响应
|
||||
* @param authentication 登录的authenticationException 对象
|
||||
* @param request 请求
|
||||
* @param response 响应
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void handle(AuthenticationException authenticationException, Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
|
||||
public void handle(AuthenticationException authenticationException, Authentication authentication,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
String username = authentication.getName();
|
||||
SysLog sysLog = SysLogUtils.getSysLog(request, username);
|
||||
sysLog.setTitle(username + "用户登录");
|
||||
@@ -72,4 +73,5 @@ public class PigxAuthenticationFailureEventHandler implements AuthenticationFail
|
||||
|
||||
log.info("用户:{} 登录失败,异常:{}", username, authenticationException.getLocalizedMessage());
|
||||
}
|
||||
|
||||
}
|
||||
+4
-3
@@ -41,16 +41,16 @@ import javax.servlet.http.HttpServletResponse;
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class PigxAuthenticationSuccessEventHandler implements AuthenticationSuccessHandler {
|
||||
|
||||
private final RemoteLogService logService;
|
||||
|
||||
/**
|
||||
* 处理登录成功方法
|
||||
* <p>
|
||||
* 获取到登录的authentication 对象
|
||||
*
|
||||
* @param authentication 登录对象
|
||||
* @param request 请求
|
||||
* @param response 返回
|
||||
* @param request 请求
|
||||
* @param response 返回
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
@@ -65,4 +65,5 @@ public class PigxAuthenticationSuccessEventHandler implements AuthenticationSucc
|
||||
logService.saveLog(sysLog, SecurityConstants.FROM_IN);
|
||||
log.info("用户:{} 登录成功", username);
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -19,14 +19,13 @@ import javax.sql.DataSource;
|
||||
*/
|
||||
@Service
|
||||
public class PigxClientDetailsServiceImpl extends JdbcClientDetailsService {
|
||||
|
||||
public PigxClientDetailsServiceImpl(DataSource dataSource) {
|
||||
super(dataSource);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重写原生方法支持redis缓存
|
||||
*
|
||||
* @param clientId
|
||||
* @return ClientDetails
|
||||
* @throws InvalidClientException
|
||||
@@ -34,8 +33,9 @@ public class PigxClientDetailsServiceImpl extends JdbcClientDetailsService {
|
||||
@Override
|
||||
@Cacheable(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#clientId", unless = "#result == null")
|
||||
public ClientDetails loadClientByClientId(String clientId) {
|
||||
super.setSelectClientDetailsSql(String.format(SecurityConstants.DEFAULT_SELECT_STATEMENT
|
||||
, TenantContextHolder.getTenantId()));
|
||||
super.setSelectClientDetailsSql(
|
||||
String.format(SecurityConstants.DEFAULT_SELECT_STATEMENT, TenantContextHolder.getTenantId()));
|
||||
return super.loadClientByClientId(clientId);
|
||||
}
|
||||
|
||||
}
|
||||
+8
-10
@@ -53,12 +53,13 @@ import java.util.Set;
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class PigxUserDetailsServiceImpl implements PigxUserDetailsService {
|
||||
|
||||
private final RemoteUserService remoteUserService;
|
||||
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* 用户密码登录
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return
|
||||
* @throws UsernameNotFoundException
|
||||
@@ -77,10 +78,8 @@ public class PigxUserDetailsServiceImpl implements PigxUserDetailsService {
|
||||
return userDetails;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据社交登录code 登录
|
||||
*
|
||||
* @param inStr TYPE@CODE
|
||||
* @return UserDetails
|
||||
* @throws UsernameNotFoundException
|
||||
@@ -93,7 +92,6 @@ public class PigxUserDetailsServiceImpl implements PigxUserDetailsService {
|
||||
|
||||
/**
|
||||
* 构建userdetails
|
||||
*
|
||||
* @param result 用户信息
|
||||
* @return
|
||||
*/
|
||||
@@ -111,15 +109,15 @@ public class PigxUserDetailsServiceImpl implements PigxUserDetailsService {
|
||||
dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
|
||||
|
||||
}
|
||||
Collection<? extends GrantedAuthority> authorities
|
||||
= AuthorityUtils.createAuthorityList(dbAuthsSet.toArray(new String[0]));
|
||||
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
|
||||
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
|
||||
SysUser user = info.getSysUser();
|
||||
boolean enabled = StrUtil.equals(user.getLockFlag(), CommonConstants.STATUS_NORMAL);
|
||||
// 构造security用户
|
||||
|
||||
return new PigxUser(user.getUserId(), user.getDeptId(), user.getPhone(), user.getAvatar(), user.getTenantId()
|
||||
, user.getUsername(), SecurityConstants.BCRYPT + user.getPassword()
|
||||
, enabled, true, true
|
||||
, !CommonConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
|
||||
return new PigxUser(user.getUserId(), user.getDeptId(), user.getPhone(), user.getAvatar(), user.getTenantId(),
|
||||
user.getUsername(), SecurityConstants.BCRYPT + user.getPassword(), enabled, true, true,
|
||||
!CommonConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -37,4 +37,5 @@ public class JacksonConfig {
|
||||
builder.modules(new PigxJavaTimeModule());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -33,9 +33,9 @@ public class MessageSourceConfig {
|
||||
|
||||
@Bean
|
||||
public MessageSource messageSource() {
|
||||
ReloadableResourceBundleMessageSource messageSource
|
||||
= new ReloadableResourceBundleMessageSource();
|
||||
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
|
||||
messageSource.setBasename("classpath:i18n/messages");
|
||||
return messageSource;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-2
@@ -23,13 +23,14 @@ import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/8/16
|
||||
* RestTemplate
|
||||
* @date 2018/8/16 RestTemplate
|
||||
*/
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
+1
-5
@@ -20,7 +20,6 @@ public interface CacheConstants {
|
||||
*/
|
||||
String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY:";
|
||||
|
||||
|
||||
/**
|
||||
* 菜单信息缓存
|
||||
*/
|
||||
@@ -36,13 +35,11 @@ public interface CacheConstants {
|
||||
*/
|
||||
String DICT_DETAILS = "dict_details";
|
||||
|
||||
|
||||
/**
|
||||
* oauth 客户端信息
|
||||
*/
|
||||
String CLIENT_DETAILS_KEY = "pigx_oauth:client:details";
|
||||
|
||||
|
||||
/**
|
||||
* spring boot admin 事件key
|
||||
*/
|
||||
@@ -68,13 +65,11 @@ public interface CacheConstants {
|
||||
*/
|
||||
String MP_REDIS_RELOAD_TOPIC = "mp_redis_reload_topic";
|
||||
|
||||
|
||||
/**
|
||||
* 支付 reload 事件
|
||||
*/
|
||||
String PAY_REDIS_RELOAD_TOPIC = "pay_redis_reload_topic";
|
||||
|
||||
|
||||
/**
|
||||
* 参数缓存
|
||||
*/
|
||||
@@ -84,4 +79,5 @@ public interface CacheConstants {
|
||||
* 租户缓存 (不区分租户)
|
||||
*/
|
||||
String TENANT_DETAILS = GLOBALLY + "tenant_details";
|
||||
|
||||
}
|
||||
+4
@@ -24,6 +24,7 @@ package com.pig4cloud.pigx.common.core.constant;
|
||||
* @date 2017/10/29
|
||||
*/
|
||||
public interface CommonConstants {
|
||||
|
||||
/**
|
||||
* header 中租户ID
|
||||
*/
|
||||
@@ -43,6 +44,7 @@ public interface CommonConstants {
|
||||
* 删除
|
||||
*/
|
||||
String STATUS_DEL = "1";
|
||||
|
||||
/**
|
||||
* 正常
|
||||
*/
|
||||
@@ -82,6 +84,7 @@ public interface CommonConstants {
|
||||
* 成功标记
|
||||
*/
|
||||
Integer SUCCESS = 0;
|
||||
|
||||
/**
|
||||
* 失败标记
|
||||
*/
|
||||
@@ -96,4 +99,5 @@ public interface CommonConstants {
|
||||
* 滑块验证码
|
||||
*/
|
||||
String IMAGE_CODE_TYPE = "blockPuzzle";
|
||||
|
||||
}
|
||||
+6
-2
@@ -2,16 +2,20 @@ package com.pig4cloud.pigx.common.core.constant;
|
||||
|
||||
/**
|
||||
* 分页相关的参数
|
||||
*
|
||||
* @author lishangbu
|
||||
* @date 2018/11/22
|
||||
*/
|
||||
public interface PaginationConstants {
|
||||
|
||||
/**
|
||||
* 当前页
|
||||
*/
|
||||
String CURRENT="current";
|
||||
String CURRENT = "current";
|
||||
|
||||
/**
|
||||
* 每页大小
|
||||
*/
|
||||
String SIZE="size";
|
||||
String SIZE = "size";
|
||||
|
||||
}
|
||||
+17
-9
@@ -24,22 +24,27 @@ package com.pig4cloud.pigx.common.core.constant;
|
||||
* @date 2017-12-18
|
||||
*/
|
||||
public interface SecurityConstants {
|
||||
|
||||
/**
|
||||
* 刷新
|
||||
*/
|
||||
String REFRESH_TOKEN = "refresh_token";
|
||||
|
||||
/**
|
||||
* 验证码有效期
|
||||
*/
|
||||
int CODE_TIME = 60;
|
||||
|
||||
/**
|
||||
* 验证码长度
|
||||
*/
|
||||
String CODE_SIZE = "4";
|
||||
|
||||
/**
|
||||
* 角色前缀
|
||||
*/
|
||||
String ROLE = "ROLE_";
|
||||
|
||||
/**
|
||||
* 前缀
|
||||
*/
|
||||
@@ -49,6 +54,7 @@ public interface SecurityConstants {
|
||||
* oauth 相关前缀
|
||||
*/
|
||||
String OAUTH_PREFIX = "oauth:";
|
||||
|
||||
/**
|
||||
* 项目的license
|
||||
*/
|
||||
@@ -78,6 +84,7 @@ public interface SecurityConstants {
|
||||
* 社交登录URL
|
||||
*/
|
||||
String SOCIAL_TOKEN_URL = "/mobile/token/social";
|
||||
|
||||
/**
|
||||
* 自定义登录URL
|
||||
*/
|
||||
@@ -86,21 +93,20 @@ public interface SecurityConstants {
|
||||
/**
|
||||
* 微信获取OPENID
|
||||
*/
|
||||
String WX_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token" +
|
||||
"?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
|
||||
String WX_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"
|
||||
+ "?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
|
||||
|
||||
/**
|
||||
* 微信小程序OPENID
|
||||
*/
|
||||
String MINI_APP_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/jscode2session" +
|
||||
"?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
|
||||
String MINI_APP_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/jscode2session"
|
||||
+ "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
|
||||
|
||||
/**
|
||||
* 码云获取token
|
||||
*/
|
||||
String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type=" +
|
||||
"authorization_code&code=%S&client_id=%s&redirect_uri=" +
|
||||
"%s&client_secret=%s";
|
||||
String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type="
|
||||
+ "authorization_code&code=%S&client_id=%s&redirect_uri=" + "%s&client_secret=%s";
|
||||
|
||||
/**
|
||||
* 开源中国获取token
|
||||
@@ -121,6 +127,7 @@ public interface SecurityConstants {
|
||||
* {bcrypt} 加密的特征码
|
||||
*/
|
||||
String BCRYPT = "{bcrypt}";
|
||||
|
||||
/**
|
||||
* sys_oauth_client_details 表的字段,不包括client_id、client_secret
|
||||
*/
|
||||
@@ -131,8 +138,7 @@ public interface SecurityConstants {
|
||||
/**
|
||||
* JdbcClientDetailsService 查询语句
|
||||
*/
|
||||
String BASE_FIND_STATEMENT = "select " + CLIENT_FIELDS
|
||||
+ " from sys_oauth_client_details";
|
||||
String BASE_FIND_STATEMENT = "select " + CLIENT_FIELDS + " from sys_oauth_client_details";
|
||||
|
||||
/**
|
||||
* 按条件client_id 查询
|
||||
@@ -173,6 +179,7 @@ public interface SecurityConstants {
|
||||
* 头像
|
||||
*/
|
||||
String DETAILS_AVATAR = "avatar";
|
||||
|
||||
/**
|
||||
* 用户部门字段
|
||||
*/
|
||||
@@ -197,4 +204,5 @@ public interface SecurityConstants {
|
||||
* AES 加密
|
||||
*/
|
||||
String AES = "aes";
|
||||
|
||||
}
|
||||
+3
-2
@@ -21,10 +21,10 @@ package com.pig4cloud.pigx.common.core.constant;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018年06月22日16:41:01
|
||||
* 服务名称
|
||||
* @date 2018年06月22日16:41:01 服务名称
|
||||
*/
|
||||
public interface ServiceNameConstants {
|
||||
|
||||
/**
|
||||
* 认证中心
|
||||
*/
|
||||
@@ -39,4 +39,5 @@ public interface ServiceNameConstants {
|
||||
* 分布式事务协调服务
|
||||
*/
|
||||
String TX_MANAGER = "pigx-tx-manager";
|
||||
|
||||
}
|
||||
+3
@@ -12,6 +12,7 @@ import lombok.Getter;
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DictTypeEnum {
|
||||
|
||||
/**
|
||||
* 字典类型-系统内置(不可修改)
|
||||
*/
|
||||
@@ -26,8 +27,10 @@ public enum DictTypeEnum {
|
||||
* 类型
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
||||
+4
-2
@@ -22,12 +22,12 @@ import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/8/15
|
||||
* 社交登录类型
|
||||
* @date 2018/8/15 社交登录类型
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum LoginTypeEnum {
|
||||
|
||||
/**
|
||||
* 账号密码登录
|
||||
*/
|
||||
@@ -67,8 +67,10 @@ public enum LoginTypeEnum {
|
||||
* 类型
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
||||
+2
@@ -32,8 +32,10 @@ public enum MenuTypeEnum {
|
||||
* 类型
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
||||
+4
-2
@@ -22,12 +22,12 @@ import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/9/30
|
||||
* 流程状态
|
||||
* @date 2018/9/30 流程状态
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ProcessStatusEnum {
|
||||
|
||||
/**
|
||||
* 图片资源
|
||||
*/
|
||||
@@ -42,8 +42,10 @@ public enum ProcessStatusEnum {
|
||||
* 类型
|
||||
*/
|
||||
private final String status;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
}
|
||||
+4
-2
@@ -22,12 +22,12 @@ import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/9/30
|
||||
* 资源类型
|
||||
* @date 2018/9/30 资源类型
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ResourceTypeEnum {
|
||||
|
||||
/**
|
||||
* 图片资源
|
||||
*/
|
||||
@@ -42,8 +42,10 @@ public enum ResourceTypeEnum {
|
||||
* 类型
|
||||
*/
|
||||
private final String type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
}
|
||||
+3
@@ -12,6 +12,7 @@ import lombok.Getter;
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum StyleTypeEnum {
|
||||
|
||||
/**
|
||||
* 前端类型-avue 风格
|
||||
*/
|
||||
@@ -26,8 +27,10 @@ public enum StyleTypeEnum {
|
||||
* 类型
|
||||
*/
|
||||
private String style;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
||||
+4
-2
@@ -22,12 +22,12 @@ import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/9/30
|
||||
* 流程状态
|
||||
* @date 2018/9/30 流程状态
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TaskStatusEnum {
|
||||
|
||||
/**
|
||||
* 未提交
|
||||
*/
|
||||
@@ -52,8 +52,10 @@ public enum TaskStatusEnum {
|
||||
* 类型
|
||||
*/
|
||||
private final String status;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
}
|
||||
+1
@@ -27,6 +27,7 @@ import lombok.NoArgsConstructor;
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class CheckedException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CheckedException(String message) {
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ package com.pig4cloud.pigx.common.core.exception;
|
||||
* @date 2018年06月22日16:22:15
|
||||
*/
|
||||
public class ValidateCodeException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -7285211528095468156L;
|
||||
|
||||
public ValidateCodeException() {
|
||||
@@ -32,4 +33,5 @@ public class ValidateCodeException extends RuntimeException {
|
||||
public ValidateCodeException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
||||
+13
-6
@@ -25,11 +25,18 @@ public class PigxJavaTimeModule extends SimpleModule {
|
||||
|
||||
public PigxJavaTimeModule() {
|
||||
super(PackageVersion.VERSION);
|
||||
this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
|
||||
this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
|
||||
this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
|
||||
this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
|
||||
this.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
|
||||
this.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
|
||||
this.addSerializer(LocalDateTime.class,
|
||||
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
|
||||
this.addSerializer(LocalDate.class,
|
||||
new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
|
||||
this.addSerializer(LocalTime.class,
|
||||
new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
|
||||
this.addDeserializer(LocalDateTime.class,
|
||||
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
|
||||
this.addDeserializer(LocalDate.class,
|
||||
new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
|
||||
this.addDeserializer(LocalTime.class,
|
||||
new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
|
||||
}
|
||||
|
||||
}
|
||||
+40
-36
@@ -41,52 +41,55 @@ import java.util.Objects;
|
||||
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {
|
||||
|
||||
private SensitiveTypeEnum type;
|
||||
|
||||
private Integer prefixNoMaskLen;
|
||||
|
||||
private Integer suffixNoMaskLen;
|
||||
|
||||
private String maskStr;
|
||||
|
||||
@Override
|
||||
public void serialize(final String origin, final JsonGenerator jsonGenerator,
|
||||
final SerializerProvider serializerProvider) throws IOException {
|
||||
final SerializerProvider serializerProvider) throws IOException {
|
||||
switch (type) {
|
||||
case CHINESE_NAME:
|
||||
jsonGenerator.writeString(DesensitizedUtils.chineseName(origin));
|
||||
break;
|
||||
case ID_CARD:
|
||||
jsonGenerator.writeString(DesensitizedUtils.idCardNum(origin));
|
||||
break;
|
||||
case FIXED_PHONE:
|
||||
jsonGenerator.writeString(DesensitizedUtils.fixedPhone(origin));
|
||||
break;
|
||||
case MOBILE_PHONE:
|
||||
jsonGenerator.writeString(DesensitizedUtils.mobilePhone(origin));
|
||||
break;
|
||||
case ADDRESS:
|
||||
jsonGenerator.writeString(DesensitizedUtils.address(origin));
|
||||
break;
|
||||
case EMAIL:
|
||||
jsonGenerator.writeString(DesensitizedUtils.email(origin));
|
||||
break;
|
||||
case BANK_CARD:
|
||||
jsonGenerator.writeString(DesensitizedUtils.bankCard(origin));
|
||||
break;
|
||||
case PASSWORD:
|
||||
jsonGenerator.writeString(DesensitizedUtils.password(origin));
|
||||
break;
|
||||
case KEY:
|
||||
jsonGenerator.writeString(DesensitizedUtils.key(origin));
|
||||
break;
|
||||
case CUSTOMER:
|
||||
jsonGenerator.writeString(DesensitizedUtils.desValue(origin, prefixNoMaskLen, suffixNoMaskLen, maskStr));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknow sensitive type enum " + type);
|
||||
case CHINESE_NAME:
|
||||
jsonGenerator.writeString(DesensitizedUtils.chineseName(origin));
|
||||
break;
|
||||
case ID_CARD:
|
||||
jsonGenerator.writeString(DesensitizedUtils.idCardNum(origin));
|
||||
break;
|
||||
case FIXED_PHONE:
|
||||
jsonGenerator.writeString(DesensitizedUtils.fixedPhone(origin));
|
||||
break;
|
||||
case MOBILE_PHONE:
|
||||
jsonGenerator.writeString(DesensitizedUtils.mobilePhone(origin));
|
||||
break;
|
||||
case ADDRESS:
|
||||
jsonGenerator.writeString(DesensitizedUtils.address(origin));
|
||||
break;
|
||||
case EMAIL:
|
||||
jsonGenerator.writeString(DesensitizedUtils.email(origin));
|
||||
break;
|
||||
case BANK_CARD:
|
||||
jsonGenerator.writeString(DesensitizedUtils.bankCard(origin));
|
||||
break;
|
||||
case PASSWORD:
|
||||
jsonGenerator.writeString(DesensitizedUtils.password(origin));
|
||||
break;
|
||||
case KEY:
|
||||
jsonGenerator.writeString(DesensitizedUtils.key(origin));
|
||||
break;
|
||||
case CUSTOMER:
|
||||
jsonGenerator.writeString(DesensitizedUtils.desValue(origin, prefixNoMaskLen, suffixNoMaskLen, maskStr));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknow sensitive type enum " + type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider,
|
||||
final BeanProperty beanProperty) throws JsonMappingException {
|
||||
final BeanProperty beanProperty) throws JsonMappingException {
|
||||
if (beanProperty != null) {
|
||||
if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
|
||||
Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
|
||||
@@ -94,12 +97,13 @@ public class SensitiveSerialize extends JsonSerializer<String> implements Contex
|
||||
sensitive = beanProperty.getContextAnnotation(Sensitive.class);
|
||||
}
|
||||
if (sensitive != null) {
|
||||
return new SensitiveSerialize(sensitive.type(), sensitive.prefixNoMaskLen(), sensitive.suffixNoMaskLen(), sensitive.maskStr());
|
||||
return new SensitiveSerialize(sensitive.type(), sensitive.prefixNoMaskLen(),
|
||||
sensitive.suffixNoMaskLen(), sensitive.maskStr());
|
||||
}
|
||||
}
|
||||
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
|
||||
}
|
||||
return serializerProvider.findNullValueSerializer(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+40
-41
@@ -25,46 +25,45 @@ package com.pig4cloud.pigx.common.core.sensitive;
|
||||
**/
|
||||
public enum SensitiveTypeEnum {
|
||||
|
||||
/**
|
||||
* 自定义
|
||||
*/
|
||||
CUSTOMER,
|
||||
/**
|
||||
* 用户名, 刘*华, 徐*
|
||||
*/
|
||||
CHINESE_NAME,
|
||||
/**
|
||||
* 身份证号, 110110********1234
|
||||
*/
|
||||
ID_CARD,
|
||||
/**
|
||||
* 座机号, ****1234
|
||||
*/
|
||||
FIXED_PHONE,
|
||||
/**
|
||||
* 手机号, 176****1234
|
||||
*/
|
||||
MOBILE_PHONE,
|
||||
/**
|
||||
* 地址, 北京********
|
||||
*/
|
||||
ADDRESS,
|
||||
/**
|
||||
* 电子邮件, s*****o@xx.com
|
||||
*/
|
||||
EMAIL,
|
||||
/**
|
||||
* 银行卡, 622202************1234
|
||||
*/
|
||||
BANK_CARD,
|
||||
/**
|
||||
* 密码, 永远是 ******, 与长度无关
|
||||
*/
|
||||
PASSWORD,
|
||||
/**
|
||||
* 密钥, 永远是 ******, 与长度无关
|
||||
*/
|
||||
KEY
|
||||
|
||||
/**
|
||||
* 自定义
|
||||
*/
|
||||
CUSTOMER,
|
||||
/**
|
||||
* 用户名, 刘*华, 徐*
|
||||
*/
|
||||
CHINESE_NAME,
|
||||
/**
|
||||
* 身份证号, 110110********1234
|
||||
*/
|
||||
ID_CARD,
|
||||
/**
|
||||
* 座机号, ****1234
|
||||
*/
|
||||
FIXED_PHONE,
|
||||
/**
|
||||
* 手机号, 176****1234
|
||||
*/
|
||||
MOBILE_PHONE,
|
||||
/**
|
||||
* 地址, 北京********
|
||||
*/
|
||||
ADDRESS,
|
||||
/**
|
||||
* 电子邮件, s*****o@xx.com
|
||||
*/
|
||||
EMAIL,
|
||||
/**
|
||||
* 银行卡, 622202************1234
|
||||
*/
|
||||
BANK_CARD,
|
||||
/**
|
||||
* 密码, 永远是 ******, 与长度无关
|
||||
*/
|
||||
PASSWORD,
|
||||
/**
|
||||
* 密钥, 永远是 ******, 与长度无关
|
||||
*/
|
||||
KEY
|
||||
|
||||
}
|
||||
+11
-12
@@ -39,12 +39,12 @@ import java.lang.reflect.Method;
|
||||
*/
|
||||
@UtilityClass
|
||||
public class ClassUtils extends org.springframework.util.ClassUtils {
|
||||
|
||||
private final ParameterNameDiscoverer PARAMETERNAMEDISCOVERER = new DefaultParameterNameDiscoverer();
|
||||
|
||||
/**
|
||||
* 获取方法参数信息
|
||||
*
|
||||
* @param constructor 构造器
|
||||
* @param constructor 构造器
|
||||
* @param parameterIndex 参数序号
|
||||
* @return {MethodParameter}
|
||||
*/
|
||||
@@ -56,8 +56,7 @@ public class ClassUtils extends org.springframework.util.ClassUtils {
|
||||
|
||||
/**
|
||||
* 获取方法参数信息
|
||||
*
|
||||
* @param method 方法
|
||||
* @param method 方法
|
||||
* @param parameterIndex 参数序号
|
||||
* @return {MethodParameter}
|
||||
*/
|
||||
@@ -69,18 +68,19 @@ public class ClassUtils extends org.springframework.util.ClassUtils {
|
||||
|
||||
/**
|
||||
* 获取Annotation
|
||||
*
|
||||
* @param method Method
|
||||
* @param method Method
|
||||
* @param annotationType 注解类
|
||||
* @param <A> 泛型标记
|
||||
* @param <A> 泛型标记
|
||||
* @return {Annotation}
|
||||
*/
|
||||
public <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) {
|
||||
Class<?> targetClass = method.getDeclaringClass();
|
||||
// The method may be on an interface, but we need attributes from the target class.
|
||||
// The method may be on an interface, but we need attributes from the target
|
||||
// class.
|
||||
// If the target class is null, the method will be unchanged.
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||
// If we are dealing with method with generic parameters, find the original method.
|
||||
// If we are dealing with method with generic parameters, find the original
|
||||
// method.
|
||||
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
// 先找方法,再找方法上的类
|
||||
A annotation = AnnotatedElementUtils.findMergedAnnotation(specificMethod, annotationType);
|
||||
@@ -94,10 +94,9 @@ public class ClassUtils extends org.springframework.util.ClassUtils {
|
||||
|
||||
/**
|
||||
* 获取Annotation
|
||||
*
|
||||
* @param handlerMethod HandlerMethod
|
||||
* @param handlerMethod HandlerMethod
|
||||
* @param annotationType 注解类
|
||||
* @param <A> 泛型标记
|
||||
* @param <A> 泛型标记
|
||||
* @return {Annotation}
|
||||
*/
|
||||
public <A extends Annotation> A getAnnotation(HandlerMethod handlerMethod, Class<A> annotationType) {
|
||||
|
||||
+7
-17
@@ -17,7 +17,6 @@
|
||||
|
||||
package com.pig4cloud.pigx.common.core.util;
|
||||
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
@@ -30,11 +29,10 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 对字符串进行脱敏操作
|
||||
*
|
||||
* @param origin 原始字符串
|
||||
* @param origin 原始字符串
|
||||
* @param prefixNoMaskLen 左侧需要保留几位明文字段
|
||||
* @param suffixNoMaskLen 右侧需要保留几位明文字段
|
||||
* @param maskStr 用于遮罩的字符串, 如'*'
|
||||
* @param maskStr 用于遮罩的字符串, 如'*'
|
||||
* @return 脱敏后结果
|
||||
*/
|
||||
public static String desValue(String origin, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {
|
||||
@@ -59,7 +57,6 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 【中文姓名】只显示最后一个汉字,其他隐藏为星号,比如:**梦
|
||||
*
|
||||
* @param fullName 姓名
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -72,7 +69,6 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 【身份证号】显示前六位, 四位,其他隐藏。共计18位或者15位,比如:340304*******1234
|
||||
*
|
||||
* @param id 身份证号码
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -82,7 +78,6 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 【固定电话】后四位,其他隐藏,比如 ****1234
|
||||
*
|
||||
* @param num 固定电话
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -92,7 +87,6 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 【手机号码】前三位,后四位,其他隐藏,比如135****6810
|
||||
*
|
||||
* @param num 手机号码
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -102,7 +96,6 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 【地址】只显示到地区,不显示详细地址,比如:北京市海淀区****
|
||||
*
|
||||
* @param address 地址
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -112,7 +105,6 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 【电子邮箱 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示,比如:d**@126.com
|
||||
*
|
||||
* @param email 电子邮箱
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -131,7 +123,6 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 【银行卡号】前六位,后四位,其他用星号隐藏每位1个星号,比如:622260**********1234
|
||||
*
|
||||
* @param cardNum 银行卡号
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -141,7 +132,6 @@ public class DesensitizedUtils {
|
||||
|
||||
/**
|
||||
* 【密码】密码的全部字符都用*代替,比如:******
|
||||
*
|
||||
* @param password 密码
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -153,9 +143,7 @@ public class DesensitizedUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 【密钥】密钥除了最后三位,全部都用*代替,比如:***xdS
|
||||
* 脱敏后长度为6,如果明文长度不足三位,则按实际长度显示,剩余位置补*
|
||||
*
|
||||
* 【密钥】密钥除了最后三位,全部都用*代替,比如:***xdS 脱敏后长度为6,如果明文长度不足三位,则按实际长度显示,剩余位置补*
|
||||
* @param key 密钥
|
||||
* @return 结果
|
||||
*/
|
||||
@@ -167,13 +155,15 @@ public class DesensitizedUtils {
|
||||
StringBuilder tmpKey = new StringBuilder(desValue(key, 0, 3, "*"));
|
||||
if (tmpKey.length() > viewLength) {
|
||||
return tmpKey.substring(tmpKey.length() - viewLength);
|
||||
} else if (tmpKey.length() < viewLength) {
|
||||
}
|
||||
else if (tmpKey.length() < viewLength) {
|
||||
int buffLength = viewLength - tmpKey.length();
|
||||
for (int i = 0; i < buffLength; i++) {
|
||||
tmpKey.insert(0, "*");
|
||||
}
|
||||
return tmpKey.toString();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return tmpKey.toString();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -40,6 +40,7 @@ import java.io.Serializable;
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(value = "响应信息主体")
|
||||
public class R<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Getter
|
||||
@@ -52,7 +53,6 @@ public class R<T> implements Serializable {
|
||||
@ApiModelProperty(value = "返回信息")
|
||||
private String msg;
|
||||
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ApiModelProperty(value = "数据")
|
||||
@@ -93,4 +93,5 @@ public class R<T> implements Serializable {
|
||||
apiResult.setMsg(msg);
|
||||
return apiResult;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-3
@@ -29,8 +29,7 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/6/27
|
||||
* Spring 工具类
|
||||
* @date 2018/6/27 Spring 工具类
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -81,7 +80,6 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
|
||||
|
||||
/**
|
||||
* 发布事件
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public static void publishEvent(ApplicationEvent event) {
|
||||
|
||||
+27
-34
@@ -41,7 +41,6 @@ import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* Miscellaneous utilities for web applications.
|
||||
*
|
||||
@@ -50,13 +49,13 @@ import java.util.Optional;
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
private final String BASIC_ = "Basic ";
|
||||
|
||||
private final String UNKNOWN = "unknown";
|
||||
|
||||
/**
|
||||
* 判断是否ajax请求
|
||||
* spring ajax 返回含有 ResponseBody 或者 RestController注解
|
||||
*
|
||||
* 判断是否ajax请求 spring ajax 返回含有 ResponseBody 或者 RestController注解
|
||||
* @param handlerMethod HandlerMethod
|
||||
* @return 是否ajax请求
|
||||
*/
|
||||
@@ -67,7 +66,6 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
/**
|
||||
* 读取cookie
|
||||
*
|
||||
* @param name cookie name
|
||||
* @return cookie value
|
||||
*/
|
||||
@@ -79,9 +77,8 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
/**
|
||||
* 读取cookie
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
* @param name cookie name
|
||||
* @param name cookie name
|
||||
* @return cookie value
|
||||
*/
|
||||
public String getCookieVal(HttpServletRequest request, String name) {
|
||||
@@ -91,9 +88,8 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
/**
|
||||
* 清除 某个指定的cookie
|
||||
*
|
||||
* @param response HttpServletResponse
|
||||
* @param key cookie key
|
||||
* @param key cookie key
|
||||
*/
|
||||
public void removeCookie(HttpServletResponse response, String key) {
|
||||
setCookie(response, key, null, 0);
|
||||
@@ -101,10 +97,9 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
/**
|
||||
* 设置cookie
|
||||
*
|
||||
* @param response HttpServletResponse
|
||||
* @param name cookie name
|
||||
* @param value cookie value
|
||||
* @param response HttpServletResponse
|
||||
* @param name cookie name
|
||||
* @param value cookie value
|
||||
* @param maxAgeInSeconds maxage
|
||||
*/
|
||||
public void setCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds) {
|
||||
@@ -117,21 +112,20 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
/**
|
||||
* 获取 HttpServletRequest
|
||||
*
|
||||
* @return {HttpServletRequest}
|
||||
*/
|
||||
public HttpServletRequest getRequest() {
|
||||
try {
|
||||
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
|
||||
return ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||
} catch (IllegalStateException e) {
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 HttpServletResponse
|
||||
*
|
||||
* @return {HttpServletResponse}
|
||||
*/
|
||||
public HttpServletResponse getResponse() {
|
||||
@@ -140,9 +134,8 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
/**
|
||||
* 返回json
|
||||
*
|
||||
* @param response HttpServletResponse
|
||||
* @param result 结果对象
|
||||
* @param result 结果对象
|
||||
*/
|
||||
public void renderJson(HttpServletResponse response, Object result) {
|
||||
renderJson(response, result, MediaType.APPLICATION_JSON_VALUE);
|
||||
@@ -150,9 +143,8 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
/**
|
||||
* 返回json
|
||||
*
|
||||
* @param response HttpServletResponse
|
||||
* @param result 结果对象
|
||||
* @param response HttpServletResponse
|
||||
* @param result 结果对象
|
||||
* @param contentType contentType
|
||||
*/
|
||||
public void renderJson(HttpServletResponse response, Object result, String contentType) {
|
||||
@@ -160,14 +152,14 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
response.setContentType(contentType);
|
||||
try (PrintWriter out = response.getWriter()) {
|
||||
out.append(JSONUtil.toJsonStr(result));
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取ip
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
public String getIP() {
|
||||
@@ -176,7 +168,6 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
|
||||
/**
|
||||
* 获取ip
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
* @return {String}
|
||||
*/
|
||||
@@ -210,18 +201,19 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
* @param defVal
|
||||
* @return 如果解析失败返回默认值
|
||||
*/
|
||||
public String extractClientId(String header,final String defVal) {
|
||||
public String extractClientId(String header, final String defVal) {
|
||||
|
||||
if (header == null || !header.startsWith(BASIC_)) {
|
||||
log.debug("请求头中client信息为空: {}",header);
|
||||
log.debug("请求头中client信息为空: {}", header);
|
||||
return defVal;
|
||||
}
|
||||
byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);
|
||||
byte[] decoded;
|
||||
try {
|
||||
decoded = Base64.decode(base64Token);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.debug("Failed to decode basic authentication token: {}",header);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
log.debug("Failed to decode basic authentication token: {}", header);
|
||||
return defVal;
|
||||
}
|
||||
|
||||
@@ -230,7 +222,7 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
int delim = token.indexOf(":");
|
||||
|
||||
if (delim == -1) {
|
||||
log.debug("Invalid basic authentication token: {}",header);
|
||||
log.debug("Invalid basic authentication token: {}", header);
|
||||
return defVal;
|
||||
}
|
||||
return token.substring(0, delim);
|
||||
@@ -241,19 +233,20 @@ public class WebUtils extends org.springframework.web.util.WebUtils {
|
||||
* @param header
|
||||
* @return
|
||||
*/
|
||||
public Optional<String> extractClientId(String header){
|
||||
return Optional.ofNullable(extractClientId(header,null));
|
||||
public Optional<String> extractClientId(String header) {
|
||||
return Optional.ofNullable(extractClientId(header, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从request 获取CLIENT_ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getClientId(String header) {
|
||||
String clientId = extractClientId(header,null);
|
||||
if(clientId == null){
|
||||
String clientId = extractClientId(header, null);
|
||||
if (clientId == null) {
|
||||
throw new CheckedException("Invalid basic authentication token");
|
||||
}
|
||||
return clientId;
|
||||
}
|
||||
|
||||
}
|
||||
+28
-26
@@ -35,16 +35,17 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* {@link RedisCacheWriter} implementation capable of reading/writing binary data from/to Redis in {@literal standalone}
|
||||
* and {@literal cluster} environments. Works upon a given {@link RedisConnectionFactory} to obtain the actual
|
||||
* {@link RedisConnection}. <br />
|
||||
* {@link RedisCacheWriter} implementation capable of reading/writing binary data from/to
|
||||
* Redis in {@literal standalone} and {@literal cluster} environments. Works upon a given
|
||||
* {@link RedisConnectionFactory} to obtain the actual {@link RedisConnection}. <br />
|
||||
* {@link DefaultRedisCacheWriter} can be used in
|
||||
* {@link RedisCacheWriter#lockingRedisCacheWriter(RedisConnectionFactory) locking} or
|
||||
* {@link RedisCacheWriter#nonLockingRedisCacheWriter(RedisConnectionFactory) non-locking} mode. While
|
||||
* {@literal non-locking} aims for maximum performance it may result in overlapping, non atomic, command execution for
|
||||
* operations spanning multiple Redis interactions like {@code putIfAbsent}. The {@literal locking} counterpart prevents
|
||||
* command overlap by setting an explicit lock key and checking against presence of this key which leads to additional
|
||||
* requests and potential command wait times.
|
||||
* {@link RedisCacheWriter#nonLockingRedisCacheWriter(RedisConnectionFactory) non-locking}
|
||||
* mode. While {@literal non-locking} aims for maximum performance it may result in
|
||||
* overlapping, non atomic, command execution for operations spanning multiple Redis
|
||||
* interactions like {@code putIfAbsent}. The {@literal locking} counterpart prevents
|
||||
* command overlap by setting an explicit lock key and checking against presence of this
|
||||
* key which leads to additional requests and potential command wait times.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
@@ -53,6 +54,7 @@ import java.util.function.Function;
|
||||
class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
|
||||
private final RedisConnectionFactory connectionFactory;
|
||||
|
||||
private final Duration sleepTime;
|
||||
|
||||
/**
|
||||
@@ -64,8 +66,8 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
|
||||
/**
|
||||
* @param connectionFactory must not be {@literal null}.
|
||||
* @param sleepTime sleep time between lock request attempts. Must not be {@literal null}. Use {@link Duration#ZERO}
|
||||
* to disable locking.
|
||||
* @param sleepTime sleep time between lock request attempts. Must not be
|
||||
* {@literal null}. Use {@link Duration#ZERO} to disable locking.
|
||||
*/
|
||||
private DefaultRedisCacheWriter(RedisConnectionFactory connectionFactory, Duration sleepTime) {
|
||||
|
||||
@@ -87,7 +89,8 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
|
||||
if (shouldExpireWithin(ttl)) {
|
||||
connection.set(key, value, Expiration.from(ttl.toMillis(), TimeUnit.MILLISECONDS), SetOption.upsert());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
connection.set(key, value);
|
||||
}
|
||||
|
||||
@@ -95,7 +98,6 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] get(String name, byte[] key) {
|
||||
|
||||
@@ -105,7 +107,6 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
return execute(name, connection -> connection.get(key));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl) {
|
||||
|
||||
@@ -129,7 +130,8 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
}
|
||||
|
||||
return connection.get(key);
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
|
||||
if (isLockingCacheWriter()) {
|
||||
doUnlock(name, connection);
|
||||
@@ -138,7 +140,6 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void remove(String name, byte[] key) {
|
||||
|
||||
@@ -148,7 +149,6 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
execute(name, connection -> connection.del(key));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clean(String name, byte[] pattern) {
|
||||
|
||||
@@ -167,12 +167,13 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
}
|
||||
|
||||
byte[][] keys = Optional.ofNullable(connection.keys(pattern)).orElse(Collections.emptySet())
|
||||
.toArray(new byte[0][]);
|
||||
.toArray(new byte[0][]);
|
||||
|
||||
if (keys.length > 0) {
|
||||
connection.del(keys);
|
||||
}
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
|
||||
if (wasLocked && isLockingCacheWriter()) {
|
||||
doUnlock(name, connection);
|
||||
@@ -185,7 +186,6 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
|
||||
/**
|
||||
* Explicitly set a write lock on a cache.
|
||||
*
|
||||
* @param name the name of the cache to lock.
|
||||
*/
|
||||
void lock(String name) {
|
||||
@@ -194,7 +194,6 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
|
||||
/**
|
||||
* Explicitly remove a write lock from a cache.
|
||||
*
|
||||
* @param name the name of the cache to unlock.
|
||||
*/
|
||||
void unlock(String name) {
|
||||
@@ -227,7 +226,8 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
|
||||
checkAndPotentiallyWaitUntilUnlocked(name, connection);
|
||||
return callback.apply(connection);
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,8 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
|
||||
try {
|
||||
callback.accept(connection);
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
@@ -254,13 +255,14 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
while (doCheckLock(name, connection)) {
|
||||
Thread.sleep(sleepTime.toMillis());
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
|
||||
// Re-interrupt current thread, to allow other participants to react.
|
||||
Thread.currentThread().interrupt();
|
||||
|
||||
throw new PessimisticLockingFailureException(String.format("Interrupted while waiting to unlock cache %s", name),
|
||||
ex);
|
||||
throw new PessimisticLockingFailureException(
|
||||
String.format("Interrupted while waiting to unlock cache %s", name), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,5 +273,5 @@ class DefaultRedisCacheWriter implements RedisCacheWriter {
|
||||
private static byte[] createCacheLockKey(String name) {
|
||||
return (name + "~lock").getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+4
-2
@@ -43,11 +43,13 @@ import java.util.Map;
|
||||
*/
|
||||
@Slf4j
|
||||
public class RedisAutoCacheManager extends RedisCacheManager {
|
||||
|
||||
private static final String SPLIT_FLAG = "#";
|
||||
|
||||
private static final int CACHE_LENGTH = 2;
|
||||
|
||||
RedisAutoCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration,
|
||||
Map<String, RedisCacheConfiguration> initialCacheConfigurations, boolean allowInFlightCacheCreation) {
|
||||
Map<String, RedisCacheConfiguration> initialCacheConfigurations, boolean allowInFlightCacheCreation) {
|
||||
super(cacheWriter, defaultCacheConfiguration, initialCacheConfigurations, allowInFlightCacheCreation);
|
||||
}
|
||||
|
||||
@@ -71,7 +73,6 @@ public class RedisAutoCacheManager extends RedisCacheManager {
|
||||
|
||||
/**
|
||||
* 从上下文中获取租户ID,重写@Cacheable value 值
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
@@ -83,4 +84,5 @@ public class RedisAutoCacheManager extends RedisCacheManager {
|
||||
}
|
||||
return super.getCache(TenantContextHolder.getTenantId() + StrUtil.COLON + name);
|
||||
}
|
||||
|
||||
}
|
||||
+14
-9
@@ -46,19 +46,21 @@ import java.util.Map;
|
||||
* @author L.cm
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter({RedisAutoConfiguration.class})
|
||||
@ConditionalOnBean({RedisConnectionFactory.class})
|
||||
@ConditionalOnMissingBean({CacheManager.class})
|
||||
@AutoConfigureAfter({ RedisAutoConfiguration.class })
|
||||
@ConditionalOnBean({ RedisConnectionFactory.class })
|
||||
@ConditionalOnMissingBean({ CacheManager.class })
|
||||
@EnableConfigurationProperties(CacheProperties.class)
|
||||
public class RedisCacheAutoConfiguration {
|
||||
|
||||
private final CacheProperties cacheProperties;
|
||||
|
||||
private final CacheManagerCustomizers customizerInvoker;
|
||||
|
||||
@Nullable
|
||||
private final RedisCacheConfiguration redisCacheConfiguration;
|
||||
|
||||
RedisCacheAutoConfiguration(CacheProperties cacheProperties,
|
||||
CacheManagerCustomizers customizerInvoker,
|
||||
ObjectProvider<RedisCacheConfiguration> redisCacheConfiguration) {
|
||||
RedisCacheAutoConfiguration(CacheProperties cacheProperties, CacheManagerCustomizers customizerInvoker,
|
||||
ObjectProvider<RedisCacheConfiguration> redisCacheConfiguration) {
|
||||
this.cacheProperties = cacheProperties;
|
||||
this.customizerInvoker = customizerInvoker;
|
||||
this.redisCacheConfiguration = redisCacheConfiguration.getIfAvailable();
|
||||
@@ -76,7 +78,7 @@ public class RedisCacheAutoConfiguration {
|
||||
initialCaches.putAll(cacheConfigMap);
|
||||
}
|
||||
RedisAutoCacheManager cacheManager = new RedisAutoCacheManager(redisCacheWriter, cacheConfiguration,
|
||||
initialCaches, true);
|
||||
initialCaches, true);
|
||||
cacheManager.setTransactionAware(false);
|
||||
return this.customizerInvoker.customize(cacheManager);
|
||||
}
|
||||
@@ -84,10 +86,12 @@ public class RedisCacheAutoConfiguration {
|
||||
private RedisCacheConfiguration determineConfiguration(ClassLoader classLoader) {
|
||||
if (this.redisCacheConfiguration != null) {
|
||||
return this.redisCacheConfiguration;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
CacheProperties.Redis redisProperties = this.cacheProperties.getRedis();
|
||||
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
|
||||
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(classLoader)));
|
||||
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair
|
||||
.fromSerializer(new JdkSerializationRedisSerializer(classLoader)));
|
||||
if (redisProperties.getTimeToLive() != null) {
|
||||
config = config.entryTtl(redisProperties.getTimeToLive());
|
||||
}
|
||||
@@ -107,4 +111,5 @@ public class RedisCacheAutoConfiguration {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -37,7 +37,8 @@ public class RedisCacheManagerConfig {
|
||||
|
||||
@Bean
|
||||
public CacheManagerCustomizers cacheManagerCustomizers(
|
||||
ObjectProvider<List<CacheManagerCustomizer<?>>> customizers) {
|
||||
ObjectProvider<List<CacheManagerCustomizer<?>>> customizers) {
|
||||
return new CacheManagerCustomizers(customizers.getIfAvailable());
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -29,7 +29,7 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* RedisTemplate 配置
|
||||
* RedisTemplate 配置
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@@ -49,4 +49,5 @@ public class RedisTemplateConfig {
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-2
@@ -26,12 +26,12 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/8/30
|
||||
* 数据权限查询参数
|
||||
* @date 2018/8/30 数据权限查询参数
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DataScope extends HashMap {
|
||||
|
||||
/**
|
||||
* 限制范围的字段名称
|
||||
*/
|
||||
@@ -46,4 +46,5 @@ public class DataScope extends HashMap {
|
||||
* 是否只查询本部门
|
||||
*/
|
||||
private Boolean isOnly = false;
|
||||
|
||||
}
|
||||
+1
-1
@@ -29,9 +29,9 @@ public interface DataScopeHandle {
|
||||
|
||||
/**
|
||||
* 计算用户数据权限
|
||||
*
|
||||
* @param deptList 部门ID,如果为空表示没有任何数据权限。
|
||||
* @return 返回true表示无需进行数据过滤处理,返回false表示需要进行数据过滤
|
||||
*/
|
||||
Boolean calcScope(List<Integer> deptList);
|
||||
|
||||
}
|
||||
+11
-11
@@ -37,7 +37,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2020/5/27
|
||||
@@ -46,8 +45,10 @@ import java.util.Properties;
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
|
||||
@Intercepts({
|
||||
@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
|
||||
public class DataScopeInterceptor extends AbstractSqlParserHandler implements Interceptor {
|
||||
|
||||
private final DataScopeHandle dataScopeHandle;
|
||||
|
||||
@Override
|
||||
@@ -66,7 +67,7 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
|
||||
String originalSql = boundSql.getSql();
|
||||
Object parameterObject = boundSql.getParameterObject();
|
||||
|
||||
//查找参数中包含DataScope类型的参数
|
||||
// 查找参数中包含DataScope类型的参数
|
||||
DataScope dataScope = findDataScopeObject(parameterObject);
|
||||
if (dataScope == null) {
|
||||
return invocation.proceed();
|
||||
@@ -79,20 +80,20 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
if(deptIds.isEmpty()){
|
||||
if (deptIds.isEmpty()) {
|
||||
originalSql = "select * from (" + originalSql + ") temp_data_scope where 1 = 2";
|
||||
}else{
|
||||
}
|
||||
else {
|
||||
String join = CollectionUtil.join(deptIds, ",");
|
||||
originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName + " in (" + join + ")";
|
||||
originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName
|
||||
+ " in (" + join + ")";
|
||||
}
|
||||
metaObject.setValue("delegate.boundSql.sql", originalSql);
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成拦截对象的代理
|
||||
*
|
||||
* @param target 目标对象
|
||||
* @return 代理对象
|
||||
*/
|
||||
@@ -106,7 +107,6 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
|
||||
|
||||
/**
|
||||
* mybatis配置的属性
|
||||
*
|
||||
* @param properties mybatis配置的属性
|
||||
*/
|
||||
@Override
|
||||
@@ -116,14 +116,14 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
|
||||
|
||||
/**
|
||||
* 查找参数是否包括DataScope对象
|
||||
*
|
||||
* @param parameterObj 参数列表
|
||||
* @return DataScope
|
||||
*/
|
||||
private DataScope findDataScopeObject(Object parameterObj) {
|
||||
if (parameterObj instanceof DataScope) {
|
||||
return (DataScope) parameterObj;
|
||||
} else if (parameterObj instanceof Map) {
|
||||
}
|
||||
else if (parameterObj instanceof Map) {
|
||||
for (Object val : ((Map<?, ?>) parameterObj).values()) {
|
||||
if (val instanceof DataScope) {
|
||||
return (DataScope) val;
|
||||
|
||||
+5
-8
@@ -16,23 +16,20 @@ public interface DataScopeMapper<T> extends BaseMapper<T> {
|
||||
|
||||
/**
|
||||
* 根据 entity 条件,查询全部记录
|
||||
*
|
||||
* @param queryWrapper 实体对象封装操作类(可以为 null)
|
||||
* @param scope 数据权限范围
|
||||
* @param scope 数据权限范围
|
||||
* @return List<T>
|
||||
*/
|
||||
List<T> selectListByScope(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper, DataScope scope);
|
||||
|
||||
|
||||
/**
|
||||
* 根据 entity 条件,查询全部记录(并翻页)
|
||||
*
|
||||
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
|
||||
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
|
||||
* @param queryWrapper 实体对象封装操作类(可以为 null)
|
||||
* @param scope 数据权限范围
|
||||
* @param scope 数据权限范围
|
||||
* @return Page
|
||||
*/
|
||||
<E extends IPage<T>> E selectPageByScope(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper, DataScope scope);
|
||||
|
||||
<E extends IPage<T>> E selectPageByScope(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper,
|
||||
DataScope scope);
|
||||
|
||||
}
|
||||
+1
@@ -18,4 +18,5 @@ public class DataScopeSqlInjector extends DefaultSqlInjector {
|
||||
methodList.add(new SelectPageByScope());
|
||||
return methodList;
|
||||
}
|
||||
|
||||
}
|
||||
+3
@@ -29,6 +29,7 @@ import lombok.Getter;
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DataScopeTypeEnum {
|
||||
|
||||
/**
|
||||
* 查询全部数据
|
||||
*/
|
||||
@@ -53,8 +54,10 @@ public enum DataScopeTypeEnum {
|
||||
* 类型
|
||||
*/
|
||||
private final int type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
}
|
||||
+10
-12
@@ -40,31 +40,29 @@ import java.util.stream.Collectors;
|
||||
* 默认data scope 判断处理器
|
||||
*/
|
||||
public class PigxDefaultDatascopeHandle implements DataScopeHandle {
|
||||
|
||||
@Autowired
|
||||
private RemoteDataScopeService dataScopeService;
|
||||
|
||||
/**
|
||||
* 计算用户数据权限
|
||||
*
|
||||
* @param deptList
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Boolean calcScope(List<Integer> deptList) {
|
||||
PigxUser user = SecurityUtils.getUser();
|
||||
List<String> roleIdList = user.getAuthorities()
|
||||
.stream().map(GrantedAuthority::getAuthority)
|
||||
List<String> roleIdList = user.getAuthorities().stream().map(GrantedAuthority::getAuthority)
|
||||
.filter(authority -> authority.startsWith(SecurityConstants.ROLE))
|
||||
.map(authority -> authority.split(StrUtil.UNDERLINE)[1])
|
||||
.collect(Collectors.toList());
|
||||
.map(authority -> authority.split(StrUtil.UNDERLINE)[1]).collect(Collectors.toList());
|
||||
// 当前用户的角色为空
|
||||
if(CollectionUtil.isEmpty(roleIdList)){
|
||||
if (CollectionUtil.isEmpty(roleIdList)) {
|
||||
return false;
|
||||
}
|
||||
SysRole role = dataScopeService.getRoleList(roleIdList).getData().stream()
|
||||
.min(Comparator.comparingInt(SysRole::getDsType)).orElse(null);
|
||||
// 角色有可能已经删除了
|
||||
if(role == null){
|
||||
if (role == null) {
|
||||
return false;
|
||||
}
|
||||
Integer dsType = role.getDsType();
|
||||
@@ -75,14 +73,13 @@ public class PigxDefaultDatascopeHandle implements DataScopeHandle {
|
||||
// 自定义
|
||||
if (DataScopeTypeEnum.CUSTOM.getType() == dsType) {
|
||||
String dsScope = role.getDsScope();
|
||||
deptList.addAll(Arrays.stream(dsScope.split(StrUtil.COMMA))
|
||||
.map(Integer::parseInt).collect(Collectors.toList()));
|
||||
deptList.addAll(
|
||||
Arrays.stream(dsScope.split(StrUtil.COMMA)).map(Integer::parseInt).collect(Collectors.toList()));
|
||||
}
|
||||
// 查询本级及其下级
|
||||
if (DataScopeTypeEnum.OWN_CHILD_LEVEL.getType() == dsType) {
|
||||
List<Integer> deptIdList = dataScopeService.getDescendantList(user.getDeptId())
|
||||
.getData().stream().map(SysDeptRelation::getDescendant)
|
||||
.collect(Collectors.toList());
|
||||
List<Integer> deptIdList = dataScopeService.getDescendantList(user.getDeptId()).getData().stream()
|
||||
.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
|
||||
deptList.addAll(deptIdList);
|
||||
}
|
||||
// 只查询本级
|
||||
@@ -91,4 +88,5 @@ public class PigxDefaultDatascopeHandle implements DataScopeHandle {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+4
-2
@@ -11,12 +11,14 @@ import org.apache.ibatis.mapping.SqlSource;
|
||||
* @date 2020/4/26
|
||||
*/
|
||||
public class SelectListByScope extends AbstractMethod {
|
||||
|
||||
@Override
|
||||
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
|
||||
SqlMethod sqlMethod = SqlMethod.SELECT_LIST;
|
||||
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlSelectColumns(tableInfo, true), tableInfo.getTableName(),
|
||||
sqlWhereEntityWrapper(true, tableInfo), sqlComment());
|
||||
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlSelectColumns(tableInfo, true),
|
||||
tableInfo.getTableName(), sqlWhereEntityWrapper(true, tableInfo), sqlComment());
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
|
||||
return this.addSelectMappedStatementForTable(mapperClass, "selectListByScope", sqlSource, tableInfo);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-3
@@ -17,13 +17,12 @@ import java.sql.SQLException;
|
||||
/**
|
||||
* Mybatis数组,符串互转
|
||||
* <p>
|
||||
* MappedJdbcTypes 数据库中的数据类型
|
||||
* MappedTypes java中的的数据类型
|
||||
* MappedJdbcTypes 数据库中的数据类型 MappedTypes java中的的数据类型
|
||||
*
|
||||
* @author xuzihui
|
||||
* @date 2019-11-20
|
||||
*/
|
||||
@MappedTypes(value = {String[].class})
|
||||
@MappedTypes(value = { String[].class })
|
||||
@MappedJdbcTypes(value = JdbcType.VARCHAR)
|
||||
public class JsonStringArrayTypeHandler extends BaseTypeHandler<String[]> {
|
||||
|
||||
|
||||
+1
-4
@@ -48,7 +48,6 @@ public class MybatisPlusConfiguration {
|
||||
|
||||
/**
|
||||
* 创建租户维护处理器对象
|
||||
*
|
||||
* @return 处理后的租户维护处理器
|
||||
*/
|
||||
@Bean
|
||||
@@ -59,7 +58,6 @@ public class MybatisPlusConfiguration {
|
||||
|
||||
/**
|
||||
* 分页插件
|
||||
*
|
||||
* @param tenantHandler 租户处理器
|
||||
* @return PaginationInterceptor
|
||||
*/
|
||||
@@ -78,7 +76,6 @@ public class MybatisPlusConfiguration {
|
||||
|
||||
/**
|
||||
* pigx 默认数据权限处理
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@@ -89,7 +86,6 @@ public class MybatisPlusConfiguration {
|
||||
|
||||
/**
|
||||
* 数据权限插件
|
||||
*
|
||||
* @return DataScopeInterceptor
|
||||
*/
|
||||
@Bean
|
||||
@@ -104,4 +100,5 @@ public class MybatisPlusConfiguration {
|
||||
public DataScopeSqlInjector dataScopeSqlInjector() {
|
||||
return new DataScopeSqlInjector();
|
||||
}
|
||||
|
||||
}
|
||||
+3
-6
@@ -17,8 +17,7 @@ public class ParamResolver {
|
||||
|
||||
/**
|
||||
* 根据key 查询value 配置
|
||||
*
|
||||
* @param key key
|
||||
* @param key key
|
||||
* @param defaultVal 默认值
|
||||
* @return value
|
||||
*/
|
||||
@@ -26,11 +25,9 @@ public class ParamResolver {
|
||||
return checkAndGet(key, defaultVal);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据key 查询value 配置
|
||||
*
|
||||
* @param key key
|
||||
* @param key key
|
||||
* @param defaultVal 默认值
|
||||
* @return value
|
||||
*/
|
||||
@@ -38,7 +35,6 @@ public class ParamResolver {
|
||||
return checkAndGet(key, defaultVal);
|
||||
}
|
||||
|
||||
|
||||
private <T> T checkAndGet(String key, Object... defaultVal) {
|
||||
// 校验入参是否合法
|
||||
if (StrUtil.isBlank(key) || defaultVal.length > 1) {
|
||||
@@ -58,4 +54,5 @@ public class ParamResolver {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+15
-16
@@ -43,12 +43,12 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Slf4j
|
||||
public class SqlFilterArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
private final static String[] KEYWORDS = {"master", "truncate", "insert", "select"
|
||||
, "delete", "update", "declare", "alter", "drop", "sleep"};
|
||||
|
||||
private final static String[] KEYWORDS = { "master", "truncate", "insert", "select", "delete", "update", "declare",
|
||||
"alter", "drop", "sleep" };
|
||||
|
||||
/**
|
||||
* 判断Controller是否包含page 参数
|
||||
*
|
||||
* @param parameter 参数
|
||||
* @return 是否过滤
|
||||
*/
|
||||
@@ -58,17 +58,17 @@ public class SqlFilterArgumentResolver implements HandlerMethodArgumentResolver
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parameter 入参集合
|
||||
* @param mavContainer model 和 view
|
||||
* @param webRequest web相关
|
||||
* @param parameter 入参集合
|
||||
* @param mavContainer model 和 view
|
||||
* @param webRequest web相关
|
||||
* @param binderFactory 入参解析
|
||||
* @return 检查后新的page对象
|
||||
* <p>
|
||||
* page 只支持查询 GET .如需解析POST获取请求报文体处理
|
||||
*/
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer
|
||||
, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
|
||||
|
||||
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
|
||||
@@ -87,29 +87,28 @@ public class SqlFilterArgumentResolver implements HandlerMethodArgumentResolver
|
||||
}
|
||||
|
||||
List<OrderItem> orderItemList = new ArrayList<>();
|
||||
Optional.ofNullable(ascs).ifPresent(s -> orderItemList.addAll(Arrays.stream(s)
|
||||
.filter(sqlInjectPredicate())
|
||||
.map(OrderItem::asc).collect(Collectors.toList())));
|
||||
Optional.ofNullable(descs).ifPresent(s -> orderItemList.addAll(Arrays.stream(s)
|
||||
.filter(sqlInjectPredicate())
|
||||
.map(OrderItem::desc).collect(Collectors.toList())));
|
||||
Optional.ofNullable(ascs).ifPresent(s -> orderItemList.addAll(
|
||||
Arrays.stream(s).filter(sqlInjectPredicate()).map(OrderItem::asc).collect(Collectors.toList())));
|
||||
Optional.ofNullable(descs).ifPresent(s -> orderItemList.addAll(
|
||||
Arrays.stream(s).filter(sqlInjectPredicate()).map(OrderItem::desc).collect(Collectors.toList())));
|
||||
page.addOrder(orderItemList);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断用户输入里面有没有关键字
|
||||
* 判断用户输入里面有没有关键字
|
||||
* @return Predicate
|
||||
*/
|
||||
private Predicate<String> sqlInjectPredicate() {
|
||||
return sql -> {
|
||||
for (String keyword : KEYWORDS) {
|
||||
if (StrUtil.containsIgnoreCase(sql, keyword)){
|
||||
if (StrUtil.containsIgnoreCase(sql, keyword)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -29,8 +29,10 @@ import java.util.List;
|
||||
*/
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(new SqlFilterArgumentResolver());
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
*/
|
||||
@Slf4j
|
||||
public class PigxFeignTenantInterceptor implements RequestInterceptor {
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate requestTemplate) {
|
||||
if (TenantContextHolder.getTenantId() == null) {
|
||||
@@ -36,4 +37,5 @@ public class PigxFeignTenantInterceptor implements RequestInterceptor {
|
||||
}
|
||||
requestTemplate.header(CommonConstants.TENANT_ID, TenantContextHolder.getTenantId().toString());
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -28,4 +28,5 @@ public class PigxTenantConfigProperties {
|
||||
* 多租户的数据表集合
|
||||
*/
|
||||
private List<String> tables = new ArrayList<>();
|
||||
|
||||
}
|
||||
+2
@@ -30,6 +30,7 @@ import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
*/
|
||||
@Configuration
|
||||
public class PigxTenantConfiguration {
|
||||
|
||||
@Bean
|
||||
public RequestInterceptor pigxFeignTenantInterceptor() {
|
||||
return new PigxFeignTenantInterceptor();
|
||||
@@ -39,4 +40,5 @@ public class PigxTenantConfiguration {
|
||||
public ClientHttpRequestInterceptor pigxTenantRequestInterceptor() {
|
||||
return new TenantRequestInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
+2
-3
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
*/
|
||||
@Slf4j
|
||||
public class PigxTenantHandler implements TenantHandler {
|
||||
|
||||
@Autowired
|
||||
private PigxTenantConfigProperties properties;
|
||||
|
||||
@@ -39,7 +40,6 @@ public class PigxTenantHandler implements TenantHandler {
|
||||
* 获取租户值
|
||||
* <p>
|
||||
* TODO 校验租户状态
|
||||
*
|
||||
* @return 租户值
|
||||
*/
|
||||
@Override
|
||||
@@ -55,7 +55,6 @@ public class PigxTenantHandler implements TenantHandler {
|
||||
|
||||
/**
|
||||
* 获取租户字段名
|
||||
*
|
||||
* @return 租户字段名
|
||||
*/
|
||||
@Override
|
||||
@@ -65,7 +64,6 @@ public class PigxTenantHandler implements TenantHandler {
|
||||
|
||||
/**
|
||||
* 根据表名判断是否进行过滤
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return 是否进行过滤
|
||||
*/
|
||||
@@ -79,4 +77,5 @@ public class PigxTenantHandler implements TenantHandler {
|
||||
|
||||
return !properties.getTables().contains(tableName);
|
||||
}
|
||||
|
||||
}
|
||||
+31
-23
@@ -8,8 +8,7 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* 租户运行时代理<br/>
|
||||
* 这是一个工具类,用于切换租户运行时,保护租户ID上下文<br/>
|
||||
* 下面这段代码演示问题所在
|
||||
* <pre>
|
||||
* 下面这段代码演示问题所在 <pre>
|
||||
* void methodA(){
|
||||
* // 因为某些特殊原因,需要手动指定租户
|
||||
* TenantContextHolder.setTenantId(1);
|
||||
@@ -22,10 +21,7 @@ import java.util.function.Supplier;
|
||||
* // 此时租户ID已经变成 1
|
||||
* // do something ...
|
||||
* }
|
||||
* </pre>
|
||||
* 嵌套设置租户ID会导致租户上下文难以维护,并且很难察觉,容易导致数据错乱。
|
||||
* 推荐的写法:
|
||||
* <pre>
|
||||
* </pre> 嵌套设置租户ID会导致租户上下文难以维护,并且很难察觉,容易导致数据错乱。 推荐的写法: <pre>
|
||||
* void methodA(){
|
||||
* TenantBroker.RunAs(1,() -> {
|
||||
* // do something ...
|
||||
@@ -49,16 +45,19 @@ public class TenantBroker {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RunAs<T> {
|
||||
|
||||
/**
|
||||
* 执行业务逻辑
|
||||
* @param tenantId
|
||||
* @throws Exception
|
||||
*/
|
||||
void run(T tenantId) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ApplyAs<T,R> {
|
||||
public interface ApplyAs<T, R> {
|
||||
|
||||
/**
|
||||
* 执行业务逻辑,返回一个值
|
||||
* @param tenantId
|
||||
@@ -66,6 +65,7 @@ public class TenantBroker {
|
||||
* @throws Exception
|
||||
*/
|
||||
R apply(T tenantId) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,16 +73,18 @@ public class TenantBroker {
|
||||
* @param tenant 租户ID
|
||||
* @param func
|
||||
*/
|
||||
public void runAs(Integer tenant,RunAs<Integer> func){
|
||||
public void runAs(Integer tenant, RunAs<Integer> func) {
|
||||
final Integer pre = TenantContextHolder.getTenantId();
|
||||
try {
|
||||
log.trace("TenantBroker 切换租户{} -> {}",pre,tenant);
|
||||
log.trace("TenantBroker 切换租户{} -> {}", pre, tenant);
|
||||
TenantContextHolder.setTenantId(tenant);
|
||||
func.run(tenant);
|
||||
} catch (Exception e){
|
||||
throw new TenantBrokerExceptionWrapper(e.getMessage(),e);
|
||||
} finally {
|
||||
log.trace("TenantBroker 还原租户{} <- {}",pre,tenant);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new TenantBrokerExceptionWrapper(e.getMessage(), e);
|
||||
}
|
||||
finally {
|
||||
log.trace("TenantBroker 还原租户{} <- {}", pre, tenant);
|
||||
TenantContextHolder.setTenantId(pre);
|
||||
}
|
||||
}
|
||||
@@ -94,16 +96,18 @@ public class TenantBroker {
|
||||
* @param <T> 返回数据类型
|
||||
* @return
|
||||
*/
|
||||
public <T> T applyAs(Integer tenant, ApplyAs<Integer,T> func){
|
||||
public <T> T applyAs(Integer tenant, ApplyAs<Integer, T> func) {
|
||||
final Integer pre = TenantContextHolder.getTenantId();
|
||||
try {
|
||||
log.trace("TenantBroker 切换租户{} -> {}",pre,tenant);
|
||||
log.trace("TenantBroker 切换租户{} -> {}", pre, tenant);
|
||||
TenantContextHolder.setTenantId(tenant);
|
||||
return func.apply(tenant);
|
||||
} catch (Exception e){
|
||||
throw new TenantBrokerExceptionWrapper(e.getMessage(),e);
|
||||
} finally {
|
||||
log.trace("TenantBroker 还原租户{} <- {}",pre,tenant);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new TenantBrokerExceptionWrapper(e.getMessage(), e);
|
||||
}
|
||||
finally {
|
||||
log.trace("TenantBroker 还原租户{} <- {}", pre, tenant);
|
||||
TenantContextHolder.setTenantId(pre);
|
||||
}
|
||||
}
|
||||
@@ -113,8 +117,8 @@ public class TenantBroker {
|
||||
* @param supplier
|
||||
* @param func
|
||||
*/
|
||||
public void runAs(Supplier<Integer> supplier, RunAs<Integer> func){
|
||||
runAs(supplier.get(),func);
|
||||
public void runAs(Supplier<Integer> supplier, RunAs<Integer> func) {
|
||||
runAs(supplier.get(), func);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,16 +128,20 @@ public class TenantBroker {
|
||||
* @param <T> 返回数据类型
|
||||
* @return
|
||||
*/
|
||||
public <T> T applyAs(Supplier<Integer> supplier, ApplyAs<Integer,T> func){
|
||||
return applyAs(supplier.get(),func);
|
||||
public <T> T applyAs(Supplier<Integer> supplier, ApplyAs<Integer, T> func) {
|
||||
return applyAs(supplier.get(), func);
|
||||
}
|
||||
|
||||
public static class TenantBrokerExceptionWrapper extends RuntimeException {
|
||||
|
||||
public TenantBrokerExceptionWrapper(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TenantBrokerExceptionWrapper(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+2
-4
@@ -22,15 +22,13 @@ import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/10/4
|
||||
* 租户工具类
|
||||
* @date 2018/10/4 租户工具类
|
||||
*/
|
||||
@UtilityClass
|
||||
public class TenantContextHolder {
|
||||
|
||||
private final ThreadLocal<Integer> THREAD_LOCAL_TENANT = new TransmittableThreadLocal<>();
|
||||
|
||||
|
||||
/**
|
||||
* TTL 设置租户ID<br/>
|
||||
* <b>谨慎使用此方法,避免嵌套调用。尽量使用 {@code TenantBroker} </b>
|
||||
@@ -43,7 +41,6 @@ public class TenantContextHolder {
|
||||
|
||||
/**
|
||||
* 获取TTL中的租户ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Integer getTenantId() {
|
||||
@@ -53,4 +50,5 @@ public class TenantContextHolder {
|
||||
public void clear() {
|
||||
THREAD_LOCAL_TENANT.remove();
|
||||
}
|
||||
|
||||
}
|
||||
+3
-1
@@ -52,11 +52,13 @@ public class TenantContextHolderFilter extends GenericFilterBean {
|
||||
|
||||
if (StrUtil.isNotBlank(tenantId)) {
|
||||
TenantContextHolder.setTenantId(Integer.parseInt(tenantId));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
TenantContextHolder.setTenantId(CommonConstants.TENANT_ID_1);
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
TenantContextHolder.clear();
|
||||
}
|
||||
|
||||
}
|
||||
+4
-1
@@ -15,9 +15,12 @@ import java.io.IOException;
|
||||
* 传递 RestTemplate 请求的租户ID
|
||||
*/
|
||||
public class TenantRequestInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
|
||||
throws IOException {
|
||||
request.getHeaders().set(CommonConstants.TENANT_ID, String.valueOf(TenantContextHolder.getTenantId()));
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
|
||||
}
|
||||
+3
@@ -41,7 +41,9 @@ import org.springframework.context.annotation.Configuration;
|
||||
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
|
||||
@EnableConfigurationProperties(DruidDataSourceProperties.class)
|
||||
public class DynamicDataSourceAutoConfiguration {
|
||||
|
||||
private final StringEncryptor stringEncryptor;
|
||||
|
||||
private final DruidDataSourceProperties properties;
|
||||
|
||||
@Bean
|
||||
@@ -53,4 +55,5 @@ public class DynamicDataSourceAutoConfiguration {
|
||||
public DsProcessor dsProcessor() {
|
||||
return new LastParamDsProcessor();
|
||||
}
|
||||
|
||||
}
|
||||
+3
-2
@@ -13,11 +13,12 @@ import java.lang.annotation.*;
|
||||
* <p>
|
||||
* 开启动态数据源
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@EnableAutoConfiguration(exclude = {DruidDataSourceAutoConfigure.class})
|
||||
@EnableAutoConfiguration(exclude = { DruidDataSourceAutoConfigure.class })
|
||||
@Import(DynamicDataSourceAutoConfiguration.class)
|
||||
public @interface EnableDynamicDataSource {
|
||||
|
||||
}
|
||||
+1
@@ -39,4 +39,5 @@ public class DruidDataSourceProperties {
|
||||
* 查询数据源的SQL
|
||||
*/
|
||||
private String queryDsSql = "select * from gen_datasource_conf where del_flag = 0";
|
||||
|
||||
}
|
||||
+3
-1
@@ -35,7 +35,9 @@ import java.util.Map;
|
||||
* 从数据源中获取 配置信息
|
||||
*/
|
||||
public class JdbcDynamicDataSourceProvider extends AbstractJdbcDataSourceProvider {
|
||||
|
||||
private final DruidDataSourceProperties properties;
|
||||
|
||||
private final StringEncryptor stringEncryptor;
|
||||
|
||||
public JdbcDynamicDataSourceProvider(StringEncryptor stringEncryptor, DruidDataSourceProperties properties) {
|
||||
@@ -46,7 +48,6 @@ public class JdbcDynamicDataSourceProvider extends AbstractJdbcDataSourceProvide
|
||||
|
||||
/**
|
||||
* 执行语句获得数据源参数
|
||||
*
|
||||
* @param statement 语句
|
||||
* @return 数据源参数
|
||||
* @throws SQLException sql异常
|
||||
@@ -76,4 +77,5 @@ public class JdbcDynamicDataSourceProvider extends AbstractJdbcDataSourceProvide
|
||||
map.put(DataSourceConstants.DS_MASTER, property);
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-5
@@ -24,16 +24,14 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
* @author lengleng
|
||||
* @date 2020/2/6
|
||||
* <p>
|
||||
* 参数数据源解析 @DS("#last)
|
||||
* 参数数据源解析 @DS("#last)
|
||||
*/
|
||||
public class LastParamDsProcessor extends DsProcessor {
|
||||
|
||||
private static final String LAST_PREFIX = "#last";
|
||||
|
||||
|
||||
/**
|
||||
* 抽象匹配条件 匹配才会走当前执行器否则走下一级执行器
|
||||
*
|
||||
* @param key DS注解里的内容
|
||||
* @return 是否匹配
|
||||
*/
|
||||
@@ -44,9 +42,8 @@ public class LastParamDsProcessor extends DsProcessor {
|
||||
|
||||
/**
|
||||
* 抽象最终决定数据源
|
||||
*
|
||||
* @param invocation 方法执行信息
|
||||
* @param key DS注解里的内容
|
||||
* @param key DS注解里的内容
|
||||
* @return 数据源名称
|
||||
*/
|
||||
@Override
|
||||
@@ -54,4 +51,5 @@ public class LastParamDsProcessor extends DsProcessor {
|
||||
Object[] arguments = invocation.getArguments();
|
||||
return String.valueOf(arguments[arguments.length - 1]);
|
||||
}
|
||||
|
||||
}
|
||||
+5
-6
@@ -33,11 +33,11 @@ import java.lang.annotation.*;
|
||||
@EnableFeignClients
|
||||
@Import(PigxFeignClientsRegistrar.class)
|
||||
public @interface EnablePigxFeignClients {
|
||||
|
||||
/**
|
||||
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
|
||||
* declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
|
||||
* {@code @ComponentScan(basePackages="org.my.pkg")}.
|
||||
*
|
||||
* @return the array of 'basePackages'.
|
||||
*/
|
||||
String[] value() default {};
|
||||
@@ -49,10 +49,9 @@ public @interface EnablePigxFeignClients {
|
||||
* <p>
|
||||
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
|
||||
* package names.
|
||||
*
|
||||
* @return the array of 'basePackages'.
|
||||
*/
|
||||
String[] basePackages() default {"com.pig4cloud.pigx"};
|
||||
String[] basePackages() default { "com.pig4cloud.pigx" };
|
||||
|
||||
/**
|
||||
* Type-safe alternative to {@link #basePackages()} for specifying the packages to
|
||||
@@ -60,7 +59,6 @@ public @interface EnablePigxFeignClients {
|
||||
* <p>
|
||||
* Consider creating a special no-op marker class or interface in each package that
|
||||
* serves no purpose other than being referenced by this attribute.
|
||||
*
|
||||
* @return the array of 'basePackageClasses'.
|
||||
*/
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
@@ -75,9 +73,10 @@ public @interface EnablePigxFeignClients {
|
||||
Class<?>[] defaultConfiguration() default {};
|
||||
|
||||
/**
|
||||
* List of classes annotated with @FeignClient. If not empty, disables classpath scanning.
|
||||
*
|
||||
* List of classes annotated with @FeignClient. If not empty, disables classpath
|
||||
* scanning.
|
||||
* @return
|
||||
*/
|
||||
Class<?>[] clients() default {};
|
||||
|
||||
}
|
||||
+14
-1
@@ -26,7 +26,9 @@ import java.util.Set;
|
||||
*/
|
||||
@Endpoint(id = "feign")
|
||||
public class FeignClientEndpoint implements SmartInitializingSingleton {
|
||||
|
||||
private final ApplicationContext context;
|
||||
|
||||
private final List<FeignClientInfo> clientList;
|
||||
|
||||
public FeignClientEndpoint(ApplicationContext context) {
|
||||
@@ -80,7 +82,8 @@ public class FeignClientEndpoint implements SmartInitializingSingleton {
|
||||
if (method.isDefault()) {
|
||||
continue;
|
||||
}
|
||||
RequestMapping requestMapping = AnnotatedElementUtils.getMergedAnnotation(method, RequestMapping.class);
|
||||
RequestMapping requestMapping = AnnotatedElementUtils.getMergedAnnotation(method,
|
||||
RequestMapping.class);
|
||||
if (requestMapping == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -96,19 +99,29 @@ public class FeignClientEndpoint implements SmartInitializingSingleton {
|
||||
@Getter
|
||||
@Setter
|
||||
public static class FeignClientInfo {
|
||||
|
||||
private String beanName;
|
||||
|
||||
private String serviceId;
|
||||
|
||||
private String contextId;
|
||||
|
||||
private String url;
|
||||
|
||||
private String path;
|
||||
|
||||
private List<ClientInfo> clientList;
|
||||
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public static class ClientInfo {
|
||||
|
||||
private final RequestMethod[] methods;
|
||||
|
||||
private final String[] mappings;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+20
-10
@@ -44,9 +44,12 @@ import java.util.Map;
|
||||
* <p>
|
||||
* feign 自动配置功能 from mica
|
||||
*/
|
||||
public class PigxFeignClientsRegistrar implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware, EnvironmentAware {
|
||||
public class PigxFeignClientsRegistrar
|
||||
implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware, EnvironmentAware {
|
||||
|
||||
@Getter
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
@Getter
|
||||
private Environment environment;
|
||||
|
||||
@@ -61,7 +64,8 @@ public class PigxFeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
}
|
||||
|
||||
private void registerFeignClients(BeanDefinitionRegistry registry) {
|
||||
List<String> feignClients = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
|
||||
List<String> feignClients = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
|
||||
getBeanClassLoader());
|
||||
// 如果 spring.factories 里为空
|
||||
if (feignClients.isEmpty()) {
|
||||
return;
|
||||
@@ -69,7 +73,8 @@ public class PigxFeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
for (String className : feignClients) {
|
||||
try {
|
||||
Class<?> clazz = beanClassLoader.loadClass(className);
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz, FeignClient.class);
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz,
|
||||
FeignClient.class);
|
||||
if (attributes == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -80,7 +85,8 @@ public class PigxFeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
registerClientConfiguration(registry, getClientName(attributes), attributes.get("configuration"));
|
||||
|
||||
validate(attributes);
|
||||
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
|
||||
BeanDefinitionBuilder definition = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(FeignClientFactoryBean.class);
|
||||
definition.addPropertyValue("url", getUrl(attributes));
|
||||
definition.addPropertyValue("path", getPath(attributes));
|
||||
String name = getName(attributes);
|
||||
@@ -92,7 +98,8 @@ public class PigxFeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
String contextId = getContextId(attributes);
|
||||
aliasBuilder.append(contextId);
|
||||
definition.addPropertyValue("contextId", contextId);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
aliasBuilder.append(name);
|
||||
}
|
||||
|
||||
@@ -117,10 +124,12 @@ public class PigxFeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
alias = qualifier;
|
||||
}
|
||||
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
|
||||
new String[] { alias });
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -129,7 +138,6 @@ public class PigxFeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
/**
|
||||
* Return the class used by {@link SpringFactoriesLoader} to load configuration
|
||||
* candidates.
|
||||
*
|
||||
* @return the factory class
|
||||
*/
|
||||
private Class<?> getSpringFactoriesLoaderFactoryClass() {
|
||||
@@ -213,14 +221,16 @@ public class PigxFeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName());
|
||||
throw new IllegalStateException(
|
||||
"Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName());
|
||||
}
|
||||
|
||||
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
|
||||
builder.addConstructorArgValue(name);
|
||||
builder.addConstructorArgValue(configuration);
|
||||
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), builder.getBeanDefinition());
|
||||
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(),
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-1
@@ -28,10 +28,11 @@ import java.lang.annotation.*;
|
||||
* <p>
|
||||
* 开启pigx 动态路由
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import(DynamicRouteAutoConfiguration.class)
|
||||
public @interface EnablePigxDynamicRoute {
|
||||
|
||||
}
|
||||
+9
-14
@@ -51,10 +51,9 @@ import java.time.Duration;
|
||||
@ComponentScan("com.pig4cloud.pigx.common.gateway")
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
|
||||
public class DynamicRouteAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 配置文件设置为空
|
||||
* redis 加载为准
|
||||
*
|
||||
* 配置文件设置为空 redis 加载为准
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@@ -64,14 +63,12 @@ public class DynamicRouteAutoConfiguration {
|
||||
|
||||
/**
|
||||
* redis 监听配置
|
||||
*
|
||||
* @param redisConnectionFactory redis 配置
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory) {
|
||||
RedisMessageListenerContainer container
|
||||
= new RedisMessageListenerContainer();
|
||||
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||
container.setConnectionFactory(redisConnectionFactory);
|
||||
container.addMessageListener((message, bytes) -> {
|
||||
log.warn("接收到重新JVM 重新加载路由事件");
|
||||
@@ -80,17 +77,15 @@ public class DynamicRouteAutoConfiguration {
|
||||
return container;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "spring.redis.cluster.enable",havingValue = "true")
|
||||
@ConditionalOnProperty(value = "spring.redis.cluster.enable", havingValue = "true")
|
||||
public LettuceConnectionFactory redisConnectionFactory(RedisProperties redisProperties) {
|
||||
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
|
||||
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(
|
||||
redisProperties.getCluster().getNodes());
|
||||
|
||||
// https://github.com/lettuce-io/lettuce-core/wiki/Redis-Cluster#user-content-refreshing-the-cluster-topology-view
|
||||
ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
|
||||
.enablePeriodicRefresh()
|
||||
.enableAllAdaptiveRefreshTriggers()
|
||||
.refreshPeriod(Duration.ofSeconds(5))
|
||||
.enablePeriodicRefresh().enableAllAdaptiveRefreshTriggers().refreshPeriod(Duration.ofSeconds(5))
|
||||
.build();
|
||||
|
||||
ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
|
||||
@@ -98,9 +93,9 @@ public class DynamicRouteAutoConfiguration {
|
||||
|
||||
// https://github.com/lettuce-io/lettuce-core/wiki/ReadFrom-Settings
|
||||
LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
|
||||
.readFrom(ReadFrom.REPLICA_PREFERRED)
|
||||
.clientOptions(clusterClientOptions).build();
|
||||
.readFrom(ReadFrom.REPLICA_PREFERRED).clientOptions(clusterClientOptions).build();
|
||||
|
||||
return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
|
||||
}
|
||||
|
||||
}
|
||||
+11
-10
@@ -26,6 +26,7 @@ import reactor.core.publisher.Mono;
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
@@ -42,16 +43,16 @@ public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler {
|
||||
response.setStatusCode(((ResponseStatusException) ex).getStatus());
|
||||
}
|
||||
|
||||
return response
|
||||
.writeWith(Mono.fromSupplier(() -> {
|
||||
DataBufferFactory bufferFactory = response.bufferFactory();
|
||||
try {
|
||||
return bufferFactory.wrap(objectMapper.writeValueAsBytes(R.failed(ex.getMessage())));
|
||||
} catch (JsonProcessingException e) {
|
||||
log.warn("Error writing response", ex);
|
||||
return bufferFactory.wrap(new byte[0]);
|
||||
}
|
||||
}));
|
||||
return response.writeWith(Mono.fromSupplier(() -> {
|
||||
DataBufferFactory bufferFactory = response.bufferFactory();
|
||||
try {
|
||||
return bufferFactory.wrap(objectMapper.writeValueAsBytes(R.failed(ex.getMessage())));
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
log.warn("Error writing response", ex);
|
||||
return bufferFactory.wrap(new byte[0]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -46,7 +46,7 @@ public class GrayLoadBalancerClientConfiguration {
|
||||
|
||||
@Bean
|
||||
public ReactiveLoadBalancerClientFilter gatewayLoadBalancerClientFilter(GrayLoadBalancer grayLoadBalancer,
|
||||
LoadBalancerProperties properties) {
|
||||
LoadBalancerProperties properties) {
|
||||
return new GrayReactiveLoadBalancerClientFilter(properties, grayLoadBalancer);
|
||||
}
|
||||
|
||||
@@ -54,4 +54,5 @@ public class GrayLoadBalancerClientConfiguration {
|
||||
public GrayLoadBalancer grayLoadBalancer(DiscoveryClient discoveryClient) {
|
||||
return new VersionGrayLoadBalancer(discoveryClient);
|
||||
}
|
||||
|
||||
}
|
||||
+9
-9
@@ -40,7 +40,9 @@ import java.net.URI;
|
||||
*/
|
||||
@Slf4j
|
||||
public class GrayReactiveLoadBalancerClientFilter extends ReactiveLoadBalancerClientFilter {
|
||||
|
||||
private static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;
|
||||
|
||||
private LoadBalancerProperties properties;
|
||||
|
||||
private GrayLoadBalancer grayLoadBalancer;
|
||||
@@ -60,23 +62,20 @@ public class GrayReactiveLoadBalancerClientFilter extends ReactiveLoadBalancerCl
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
URI url = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
|
||||
String schemePrefix = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
|
||||
if (url == null
|
||||
|| (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {
|
||||
if (url == null || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
// preserve the original url
|
||||
ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
|
||||
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName()
|
||||
+ " url before: " + url);
|
||||
log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);
|
||||
}
|
||||
|
||||
return choose(exchange).doOnNext(response -> {
|
||||
|
||||
if (!response.hasServer()) {
|
||||
throw NotFoundException.create(properties.isUse404(),
|
||||
"Unable to find instance for " + url.getHost());
|
||||
throw NotFoundException.create(properties.isUse404(), "Unable to find instance for " + url.getHost());
|
||||
}
|
||||
|
||||
URI uri = exchange.getRequest().getURI();
|
||||
@@ -88,8 +87,8 @@ public class GrayReactiveLoadBalancerClientFilter extends ReactiveLoadBalancerCl
|
||||
overrideScheme = url.getScheme();
|
||||
}
|
||||
|
||||
DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(
|
||||
response.getServer(), overrideScheme);
|
||||
DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(response.getServer(),
|
||||
overrideScheme);
|
||||
|
||||
URI requestUrl = LoadBalancerUriTools.reconstructURI(serviceInstance, uri);
|
||||
|
||||
@@ -102,7 +101,8 @@ public class GrayReactiveLoadBalancerClientFilter extends ReactiveLoadBalancerCl
|
||||
|
||||
private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {
|
||||
URI uri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
|
||||
ServiceInstance serviceInstance = grayLoadBalancer.choose(uri.getHost(),exchange.getRequest());
|
||||
ServiceInstance serviceInstance = grayLoadBalancer.choose(uri.getHost(), exchange.getRequest());
|
||||
return Mono.just(new DefaultResponse(serviceInstance));
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -30,10 +30,10 @@ public interface GrayLoadBalancer {
|
||||
|
||||
/**
|
||||
* 根据serviceId 筛选可用服务
|
||||
*
|
||||
* @param serviceId 服务ID
|
||||
* @param request 当前请求
|
||||
* @param request 当前请求
|
||||
* @return
|
||||
*/
|
||||
ServiceInstance choose(String serviceId, ServerHttpRequest request);
|
||||
|
||||
}
|
||||
+4
-4
@@ -41,21 +41,20 @@ import java.util.Map;
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class VersionGrayLoadBalancer implements GrayLoadBalancer {
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
/**
|
||||
* 根据serviceId 筛选可用服务
|
||||
*
|
||||
* @param serviceId 服务ID
|
||||
* @param request 当前请求
|
||||
* @param request 当前请求
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ServiceInstance choose(String serviceId, ServerHttpRequest request) {
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
|
||||
|
||||
//注册中心无实例 抛出异常
|
||||
// 注册中心无实例 抛出异常
|
||||
if (CollUtil.isEmpty(instances)) {
|
||||
log.warn("No instance available for {}", serviceId);
|
||||
throw new NotFoundException("No instance available for " + serviceId);
|
||||
@@ -78,4 +77,5 @@ public class VersionGrayLoadBalancer implements GrayLoadBalancer {
|
||||
}
|
||||
return instances.get(RandomUtil.randomInt(instances.size()));
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -26,7 +26,9 @@ import org.springframework.context.ApplicationEvent;
|
||||
* 路由初始化事件
|
||||
*/
|
||||
public class DynamicRouteInitEvent extends ApplicationEvent {
|
||||
|
||||
public DynamicRouteInitEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -35,16 +35,20 @@ import java.util.List;
|
||||
@RefreshScope
|
||||
@ConfigurationProperties("ribbon.rule")
|
||||
public class PigxRibbonRuleProperties {
|
||||
|
||||
/**
|
||||
* 是否开启,默认:true
|
||||
*/
|
||||
private boolean enabled = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 是否开启灰度路由,默认:false
|
||||
*/
|
||||
private boolean grayEnabled;
|
||||
|
||||
/**
|
||||
* 优先的ip列表,支持通配符,例如:10.20.0.8*、10.20.0.*
|
||||
*/
|
||||
private List<String> priorIpPattern = new ArrayList<>();
|
||||
|
||||
}
|
||||
+3
-5
@@ -44,6 +44,7 @@ import java.util.List;
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {
|
||||
|
||||
private final RedisTemplate redisTemplate;
|
||||
|
||||
@Override
|
||||
@@ -70,14 +71,10 @@ public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 动态路由入口
|
||||
* <p>
|
||||
* 1. 先从内存中获取
|
||||
* 2. 为空加载Redis中数据
|
||||
* 3. 更新内存
|
||||
*
|
||||
* 1. 先从内存中获取 2. 为空加载Redis中数据 3. 更新内存
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@@ -96,4 +93,5 @@ public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {
|
||||
RouteCacheHolder.setRouteList(values);
|
||||
return Flux.fromIterable(values);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-2
@@ -33,11 +33,11 @@ import java.util.List;
|
||||
*/
|
||||
@UtilityClass
|
||||
public class RouteCacheHolder {
|
||||
|
||||
private Cache<String, RouteDefinitionVo> cache = CacheUtil.newLFUCache(50);
|
||||
|
||||
/**
|
||||
* 获取缓存的全部对象
|
||||
*
|
||||
* @return routeList
|
||||
*/
|
||||
public List<RouteDefinitionVo> getRouteList() {
|
||||
@@ -48,7 +48,6 @@ public class RouteCacheHolder {
|
||||
|
||||
/**
|
||||
* 更新缓存
|
||||
*
|
||||
* @param routeList 缓存列表
|
||||
*/
|
||||
public void setRouteList(List<RouteDefinitionVo> routeList) {
|
||||
|
||||
+4
-4
@@ -15,8 +15,7 @@
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.common.gateway.vo
|
||||
;
|
||||
package com.pig4cloud.pigx.common.gateway.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -28,14 +27,15 @@ import java.io.Serializable;
|
||||
* @author lengleng
|
||||
* @date 2018/10/31
|
||||
* <p>
|
||||
* 扩展此类支持序列化a
|
||||
* See RouteDefinition.class
|
||||
* 扩展此类支持序列化a See RouteDefinition.class
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class RouteDefinitionVo extends RouteDefinition implements Serializable {
|
||||
|
||||
/**
|
||||
* 路由名称
|
||||
*/
|
||||
private String routeName;
|
||||
|
||||
}
|
||||
+1
@@ -46,4 +46,5 @@ public class GrayRibbonLoadBalancerConfiguration {
|
||||
public RequestInterceptor grayFeignRequestInterceptor() {
|
||||
return new GrayFeignRequestInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
+6
-4
@@ -32,19 +32,21 @@ import lombok.extern.slf4j.Slf4j;
|
||||
*/
|
||||
@Slf4j
|
||||
public class GrayFeignRequestInterceptor implements RequestInterceptor {
|
||||
|
||||
/**
|
||||
* Called for every request. Add data using methods on the supplied {@link RequestTemplate}.
|
||||
*
|
||||
* Called for every request. Add data using methods on the supplied
|
||||
* {@link RequestTemplate}.
|
||||
* @param template
|
||||
*/
|
||||
@Override
|
||||
public void apply(RequestTemplate template) {
|
||||
String reqVersion = WebUtils.getRequest() != null
|
||||
? WebUtils.getRequest().getHeader(CommonConstants.VERSION) : null;
|
||||
String reqVersion = WebUtils.getRequest() != null ? WebUtils.getRequest().getHeader(CommonConstants.VERSION)
|
||||
: null;
|
||||
|
||||
if (StrUtil.isNotBlank(reqVersion)) {
|
||||
log.debug("feign gray add header version :{}", reqVersion);
|
||||
template.header(CommonConstants.VERSION, reqVersion);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -39,6 +39,7 @@ import java.util.Map;
|
||||
*/
|
||||
@Slf4j
|
||||
public class GrayRibbonLoadBalancerRule extends AbstractLoadBalancerRule {
|
||||
|
||||
@Override
|
||||
public void initWithNiwsConfig(IClientConfig iClientConfig) {
|
||||
}
|
||||
@@ -48,19 +49,18 @@ public class GrayRibbonLoadBalancerRule extends AbstractLoadBalancerRule {
|
||||
return choose(getLoadBalancer(), key);
|
||||
}
|
||||
|
||||
|
||||
public Server choose(ILoadBalancer lb, Object key) {
|
||||
List<Server> reachableServers = lb.getReachableServers();
|
||||
|
||||
//注册中心无可用实例 抛出异常
|
||||
// 注册中心无可用实例 抛出异常
|
||||
if (CollUtil.isEmpty(reachableServers)) {
|
||||
log.warn("No instance available for {}", key);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取请求version,无则随机返回可用实例
|
||||
String reqVersion = WebUtils.getRequest() != null
|
||||
? WebUtils.getRequest().getHeader(CommonConstants.VERSION) : null;
|
||||
String reqVersion = WebUtils.getRequest() != null ? WebUtils.getRequest().getHeader(CommonConstants.VERSION)
|
||||
: null;
|
||||
if (StrUtil.isBlank(reqVersion)) {
|
||||
return reachableServers.get(RandomUtil.randomInt(reachableServers.size()));
|
||||
}
|
||||
|
||||
+1
@@ -48,4 +48,5 @@ public class XxlJobAutoConfiguration {
|
||||
xxlJobSpringExecutor.setLogRetentionDays(xxlJobProperties.getExecutor().getLogRetentionDays());
|
||||
return xxlJobSpringExecutor;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-2
@@ -28,10 +28,11 @@ import java.lang.annotation.*;
|
||||
* <p>
|
||||
* 开启支持XXL
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import({XxlJobAutoConfiguration.class})
|
||||
@Import({ XxlJobAutoConfiguration.class })
|
||||
public @interface EnablePigxXxlJob {
|
||||
|
||||
}
|
||||
+3
-2
@@ -27,9 +27,10 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
public class XxlAdminProperties {
|
||||
|
||||
/**
|
||||
* 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。
|
||||
* 执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
|
||||
* 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。 执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
|
||||
*/
|
||||
private String addresses = "http://127.0.0.1:8080/xxl-job-admin";
|
||||
|
||||
}
|
||||
+5
-5
@@ -25,21 +25,20 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
public class XxlExecutorProperties {
|
||||
|
||||
/**
|
||||
* 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
|
||||
*/
|
||||
private String appname = "xxl-job-executor";
|
||||
|
||||
/**
|
||||
* 服务注册地址,优先使用该配置作为注册地址
|
||||
* 为空时使用内嵌服务 ”IP:PORT“ 作为注册地址
|
||||
* 从而更灵活的支持容器类型执行器动态IP和动态映射端口问题
|
||||
* 服务注册地址,优先使用该配置作为注册地址 为空时使用内嵌服务 ”IP:PORT“ 作为注册地址 从而更灵活的支持容器类型执行器动态IP和动态映射端口问题
|
||||
*/
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP
|
||||
* ,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务"
|
||||
* 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP ,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和
|
||||
* "调度中心请求并触发任务"
|
||||
*/
|
||||
private String ip;
|
||||
|
||||
@@ -62,4 +61,5 @@ public class XxlExecutorProperties {
|
||||
* 执行器日志保存天数 [选填] :值大于3时生效,启用执行器Log文件定期清理功能,否则不生效;
|
||||
*/
|
||||
private Integer logRetentionDays = 30;
|
||||
|
||||
}
|
||||
+2
@@ -29,7 +29,9 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "xxl.job")
|
||||
public class XxlJobProperties {
|
||||
|
||||
private XxlAdminProperties admin = new XxlAdminProperties();
|
||||
|
||||
private XxlExecutorProperties executor = new XxlExecutorProperties();
|
||||
|
||||
}
|
||||
+2
@@ -40,6 +40,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
||||
@AllArgsConstructor
|
||||
@ConditionalOnWebApplication
|
||||
public class LogAutoConfiguration {
|
||||
|
||||
private final RemoteLogService remoteLogService;
|
||||
|
||||
@Bean
|
||||
@@ -51,4 +52,5 @@ public class LogAutoConfiguration {
|
||||
public SysLogAspect sysLogAspect(ApplicationEventPublisher publisher) {
|
||||
return new SysLogAspect(publisher);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-3
@@ -23,8 +23,7 @@ import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2018/6/28
|
||||
* 操作日志注解
|
||||
* @date 2018/6/28 操作日志注解
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -33,8 +32,8 @@ public @interface SysLog {
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
String value();
|
||||
|
||||
}
|
||||
+1
@@ -39,6 +39,7 @@ import org.springframework.context.ApplicationEventPublisher;
|
||||
@Aspect
|
||||
@AllArgsConstructor
|
||||
public class SysLogAspect {
|
||||
|
||||
private final ApplicationEventPublisher publisher;
|
||||
|
||||
@SneakyThrows
|
||||
|
||||
+3
-2
@@ -24,11 +24,12 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* 系统日志事件
|
||||
* @author lengleng 系统日志事件
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class SysLogEvent {
|
||||
|
||||
private final SysLog sysLog;
|
||||
|
||||
}
|
||||
+3
-2
@@ -29,12 +29,12 @@ import org.springframework.core.annotation.Order;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* 异步监听日志事件
|
||||
* @author lengleng 异步监听日志事件
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class SysLogListener {
|
||||
|
||||
private final RemoteLogService remoteLogService;
|
||||
|
||||
@Async
|
||||
@@ -44,4 +44,5 @@ public class SysLogListener {
|
||||
SysLog sysLog = event.getSysLog();
|
||||
remoteLogService.saveLog(sysLog, SecurityConstants.FROM_IN);
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -11,6 +11,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||
* 初始化日志路径
|
||||
*/
|
||||
public class ApplicationLoggerInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
ConfigurableEnvironment environment = applicationContext.getEnvironment();
|
||||
@@ -21,4 +22,5 @@ public class ApplicationLoggerInitializer implements ApplicationContextInitializ
|
||||
// spring boot admin 直接加载日志
|
||||
System.setProperty("logging.file.name", String.format("%s/%s/debug.log", logBase, appName));
|
||||
}
|
||||
|
||||
}
|
||||
+1
-2
@@ -41,6 +41,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@UtilityClass
|
||||
public class SysLogUtils {
|
||||
|
||||
public SysLog getSysLog() {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) Objects
|
||||
.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||
@@ -71,7 +72,6 @@ public class SysLogUtils {
|
||||
|
||||
/**
|
||||
* 获取客户端
|
||||
*
|
||||
* @return clientId
|
||||
*/
|
||||
private String getClientId() {
|
||||
@@ -85,7 +85,6 @@ public class SysLogUtils {
|
||||
|
||||
/**
|
||||
* 获取用户名称
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
private String getUsername() {
|
||||
|
||||
+2
-1
@@ -32,8 +32,9 @@ import org.springframework.context.annotation.Bean;
|
||||
* @author 858695266
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@EnableConfigurationProperties({OssProperties.class})
|
||||
@EnableConfigurationProperties({ OssProperties.class })
|
||||
public class OssAutoConfiguration {
|
||||
|
||||
private final OssProperties properties;
|
||||
|
||||
@Bean
|
||||
|
||||
+8
-16
@@ -24,24 +24,17 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* aws 配置信息
|
||||
*
|
||||
* @author lengleng
|
||||
* @author 858695266
|
||||
* 配置文件添加:
|
||||
* oss:
|
||||
* enable: true
|
||||
* endpoint: http://127.0.0.1:9000
|
||||
* # pathStyleAccess 采用nginx反向代理或者AWS S3 配置成true,支持第三方云存储配置成false
|
||||
* pathStyleAccess: false
|
||||
* access-key: lengleng
|
||||
* secret-key: lengleng
|
||||
* bucket-name: lengleng
|
||||
* region:
|
||||
* custom-domain: https://oss.xxx.com/lengleng
|
||||
* @author 858695266 配置文件添加: oss: enable: true endpoint: http://127.0.0.1:9000 #
|
||||
* pathStyleAccess 采用nginx反向代理或者AWS S3 配置成true,支持第三方云存储配置成false pathStyleAccess: false
|
||||
* access-key: lengleng secret-key: lengleng bucket-name: lengleng region: custom-domain:
|
||||
* https://oss.xxx.com/lengleng
|
||||
* <p>
|
||||
* bucket 设置公共读权限
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "oss")
|
||||
public class OssProperties {
|
||||
|
||||
/**
|
||||
* 对象存储服务的URL
|
||||
*/
|
||||
@@ -53,10 +46,9 @@ public class OssProperties {
|
||||
private String customDomain;
|
||||
|
||||
/**
|
||||
* true path-style
|
||||
* nginx 反向代理和S3默认支持 pathStyle {http://endpoint/bucketname}
|
||||
* false supports virtual-hosted-style 阿里云等需要配置为
|
||||
* virtual-hosted-style 模式{http://bucketname.endpoint}
|
||||
* true path-style nginx 反向代理和S3默认支持 pathStyle {http://endpoint/bucketname} false
|
||||
* supports virtual-hosted-style 阿里云等需要配置为 virtual-hosted-style
|
||||
* 模式{http://bucketname.endpoint}
|
||||
*/
|
||||
private Boolean pathStyleAccess = true;
|
||||
|
||||
|
||||
+5
-3
@@ -43,6 +43,7 @@ import java.util.Map;
|
||||
@AllArgsConstructor
|
||||
@RequestMapping("/aws")
|
||||
public class OssEndpoint {
|
||||
|
||||
private final OssTemplate template;
|
||||
|
||||
/**
|
||||
@@ -90,7 +91,8 @@ public class OssEndpoint {
|
||||
|
||||
@SneakyThrows
|
||||
@PostMapping("/object/{bucketName}/{objectName}")
|
||||
public S3Object createObject(@RequestBody MultipartFile object, @PathVariable String bucketName, @PathVariable String objectName) {
|
||||
public S3Object createObject(@RequestBody MultipartFile object, @PathVariable String bucketName,
|
||||
@PathVariable String objectName) {
|
||||
template.putObject(bucketName, objectName, object.getInputStream(), object.getSize(), object.getContentType());
|
||||
return template.getObjectInfo(bucketName, objectName);
|
||||
|
||||
@@ -106,7 +108,8 @@ public class OssEndpoint {
|
||||
|
||||
@SneakyThrows
|
||||
@GetMapping("/object/{bucketName}/{objectName}/{expires}")
|
||||
public Map<String, Object> getObject(@PathVariable String bucketName, @PathVariable String objectName, @PathVariable Integer expires) {
|
||||
public Map<String, Object> getObject(@PathVariable String bucketName, @PathVariable String objectName,
|
||||
@PathVariable Integer expires) {
|
||||
Map<String, Object> responseBody = new HashMap<>(8);
|
||||
// Put Object info
|
||||
responseBody.put("bucket", bucketName);
|
||||
@@ -124,5 +127,4 @@ public class OssEndpoint {
|
||||
template.removeObject(bucketName, objectName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+37
-37
@@ -37,10 +37,8 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* aws-s3 通用存储操作
|
||||
* 支持所有兼容s3协议的云存储: {阿里云OSS,腾讯云COS,七牛云,京东云,minio 等}
|
||||
* aws-s3 通用存储操作 支持所有兼容s3协议的云存储: {阿里云OSS,腾讯云COS,七牛云,京东云,minio 等}
|
||||
*
|
||||
* @author lengleng
|
||||
* @author 858695266
|
||||
@@ -49,13 +47,13 @@ import java.util.*;
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class OssTemplate implements InitializingBean {
|
||||
|
||||
private final OssProperties ossProperties;
|
||||
|
||||
private AmazonS3 amazonS3;
|
||||
|
||||
/**
|
||||
* 创建bucket
|
||||
*
|
||||
* @param bucketName bucket名称
|
||||
*/
|
||||
@SneakyThrows
|
||||
@@ -69,7 +67,8 @@ public class OssTemplate implements InitializingBean {
|
||||
* 获取全部bucket
|
||||
* <p>
|
||||
*
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListBuckets">AWS API Documentation</a>
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListBuckets">AWS
|
||||
* API Documentation</a>
|
||||
*/
|
||||
@SneakyThrows
|
||||
public List<Bucket> getAllBuckets() {
|
||||
@@ -78,7 +77,8 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* @param bucketName bucket名称
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListBuckets">AWS API Documentation</a>
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListBuckets">AWS
|
||||
* API Documentation</a>
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Optional<Bucket> getBucket(String bucketName) {
|
||||
@@ -87,7 +87,9 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* @param bucketName bucket名称
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/DeleteBucket">AWS API Documentation</a>
|
||||
* @see <a href=
|
||||
* "http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/DeleteBucket">AWS API
|
||||
* Documentation</a>
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void removeBucket(String bucketName) {
|
||||
@@ -96,12 +98,12 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* 根据文件前置查询文件
|
||||
*
|
||||
* @param bucketName bucket名称
|
||||
* @param prefix 前缀
|
||||
* @param recursive 是否递归查询
|
||||
* @param prefix 前缀
|
||||
* @param recursive 是否递归查询
|
||||
* @return S3ObjectSummary 列表
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjects">AWS API Documentation</a>
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/ListObjects">AWS
|
||||
* API Documentation</a>
|
||||
*/
|
||||
@SneakyThrows
|
||||
public List<S3ObjectSummary> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
|
||||
@@ -111,10 +113,9 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* 获取文件外链
|
||||
*
|
||||
* @param bucketName bucket名称
|
||||
* @param objectName 文件名称
|
||||
* @param expires 过期时间 <=7
|
||||
* @param expires 过期时间 <=7
|
||||
* @return url
|
||||
* @see AmazonS3#generatePresignedUrl(String bucketName, String key, Date expiration)
|
||||
*/
|
||||
@@ -130,11 +131,11 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* 获取文件
|
||||
*
|
||||
* @param bucketName bucket名称
|
||||
* @param objectName 文件名称
|
||||
* @return 二进制流
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject">AWS API Documentation</a>
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject">AWS
|
||||
* API Documentation</a>
|
||||
*/
|
||||
@SneakyThrows
|
||||
public InputStream getObject(String bucketName, String objectName) {
|
||||
@@ -143,10 +144,9 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param bucketName bucket名称
|
||||
* @param objectName 文件名称
|
||||
* @param stream 文件流
|
||||
* @param stream 文件流
|
||||
* @throws Exception
|
||||
*/
|
||||
public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
|
||||
@@ -155,17 +155,18 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param bucketName bucket名称
|
||||
* @param objectName 文件名称
|
||||
* @param stream 文件流
|
||||
* @param size 大小
|
||||
* @param bucketName bucket名称
|
||||
* @param objectName 文件名称
|
||||
* @param stream 文件流
|
||||
* @param size 大小
|
||||
* @param contextType 类型
|
||||
* @throws Exception
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/PutObject">AWS API Documentation</a>
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/PutObject">AWS
|
||||
* API Documentation</a>
|
||||
*/
|
||||
public PutObjectResult putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
|
||||
// String fileName = getFileName(objectName);
|
||||
public PutObjectResult putObject(String bucketName, String objectName, InputStream stream, long size,
|
||||
String contextType) throws Exception {
|
||||
// String fileName = getFileName(objectName);
|
||||
byte[] bytes = IOUtils.toByteArray(stream);
|
||||
ObjectMetadata objectMetadata = new ObjectMetadata();
|
||||
objectMetadata.setContentLength(size);
|
||||
@@ -178,11 +179,11 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* 获取文件信息
|
||||
*
|
||||
* @param bucketName bucket名称
|
||||
* @param objectName 文件名称
|
||||
* @throws Exception
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject">AWS API Documentation</a>
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/GetObject">AWS
|
||||
* API Documentation</a>
|
||||
*/
|
||||
public S3Object getObjectInfo(String bucketName, String objectName) throws Exception {
|
||||
return amazonS3.getObject(bucketName, objectName);
|
||||
@@ -190,11 +191,12 @@ public class OssTemplate implements InitializingBean {
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param bucketName bucket名称
|
||||
* @param objectName 文件名称
|
||||
* @throws Exception
|
||||
* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/DeleteObject">AWS API Documentation</a>
|
||||
* @see <a href=
|
||||
* "http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/DeleteObject">AWS API
|
||||
* Documentation</a>
|
||||
*/
|
||||
public void removeObject(String bucketName, String objectName) throws Exception {
|
||||
amazonS3.deleteObject(bucketName, objectName);
|
||||
@@ -205,14 +207,12 @@ public class OssTemplate implements InitializingBean {
|
||||
ClientConfiguration clientConfiguration = new ClientConfiguration();
|
||||
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
|
||||
ossProperties.getEndpoint(), ossProperties.getRegion());
|
||||
AWSCredentials awsCredentials = new BasicAWSCredentials(ossProperties.getAccessKey(), ossProperties.getSecretKey());
|
||||
AWSCredentials awsCredentials = new BasicAWSCredentials(ossProperties.getAccessKey(),
|
||||
ossProperties.getSecretKey());
|
||||
AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
|
||||
this.amazonS3 = AmazonS3Client.builder()
|
||||
.withEndpointConfiguration(endpointConfiguration)
|
||||
.withClientConfiguration(clientConfiguration)
|
||||
.withCredentials(awsCredentialsProvider)
|
||||
.disableChunkedEncoding()
|
||||
.withPathStyleAccessEnabled(ossProperties.getPathStyleAccess())
|
||||
.build();
|
||||
this.amazonS3 = AmazonS3Client.builder().withEndpointConfiguration(endpointConfiguration)
|
||||
.withClientConfiguration(clientConfiguration).withCredentials(awsCredentialsProvider)
|
||||
.disableChunkedEncoding().withPathStyleAccessEnabled(ossProperties.getPathStyleAccess()).build();
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -34,10 +34,10 @@ import java.lang.annotation.*;
|
||||
@Documented
|
||||
@Inherited
|
||||
@EnableResourceServer
|
||||
@Target({ElementType.TYPE})
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Import({PigxResourceServerAutoConfiguration.class, PigxSecurityBeanDefinitionRegistrar.class})
|
||||
@Import({ PigxResourceServerAutoConfiguration.class, PigxSecurityBeanDefinitionRegistrar.class })
|
||||
public @interface EnablePigxResourceServer {
|
||||
|
||||
}
|
||||
+2
-3
@@ -25,22 +25,21 @@ import java.lang.annotation.*;
|
||||
* <p>
|
||||
* 服务调用鉴权注解
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Inner {
|
||||
|
||||
/**
|
||||
* 是否AOP统一处理
|
||||
*
|
||||
* @return false, true
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
/**
|
||||
* 需要特殊判空的字段(预留)
|
||||
*
|
||||
* @return {}
|
||||
*/
|
||||
String[] field() default {};
|
||||
|
||||
}
|
||||
Loaded 100 of 651 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user