🎨 改进结构和代码格式. add spring-javaformat plugin and format all code

This commit is contained in:
lengleng committed 2020-06-14 17:59:04 +08:00
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);
}
}
@@ -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;
}
}
@@ -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());
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -37,4 +37,5 @@ public class JacksonConfig {
builder.modules(new PigxJavaTimeModule());
};
}
}
@@ -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;
}
}
@@ -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();
}
}
@@ -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";
}
@@ -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";
}
@@ -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";
}
@@ -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";
}
@@ -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";
}
@@ -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;
}
@@ -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;
}
@@ -32,8 +32,10 @@ public enum MenuTypeEnum {
* 类型
*/
private String type;
/**
* 描述
*/
private String description;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -27,6 +27,7 @@ import lombok.NoArgsConstructor;
*/
@NoArgsConstructor
public class CheckedException extends RuntimeException {
private static final long serialVersionUID = 1L;
public CheckedException(String message) {
@@ -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);
}
}
@@ -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)));
}
}
@@ -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);
}
}
}
@@ -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
}
@@ -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) {
@@ -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();
}
}
@@ -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;
}
}
@@ -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) {
@@ -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;
}
}
@@ -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);
}
}
}
@@ -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);
}
}
@@ -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;
}
}
}
@@ -37,7 +37,8 @@ public class RedisCacheManagerConfig {
@Bean
public CacheManagerCustomizers cacheManagerCustomizers(
ObjectProvider<List<CacheManagerCustomizer<?>>> customizers) {
ObjectProvider<List<CacheManagerCustomizer<?>>> customizers) {
return new CacheManagerCustomizers(customizers.getIfAvailable());
}
}
@@ -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;
}
}
@@ -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;
}
@@ -29,9 +29,9 @@ public interface DataScopeHandle {
/**
* 计算用户数据权限
*
* @param deptList 部门ID,如果为空表示没有任何数据权限。
* @return 返回true表示无需进行数据过滤处理,返回false表示需要进行数据过滤
*/
Boolean calcScope(List<Integer> deptList);
}
@@ -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;
@@ -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);
}
@@ -18,4 +18,5 @@ public class DataScopeSqlInjector extends DefaultSqlInjector {
methodList.add(new SelectPageByScope());
return methodList;
}
}
@@ -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;
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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[]> {
@@ -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();
}
}
@@ -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;
}
}
@@ -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;
};
}
}
@@ -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());
}
}
@@ -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());
}
}
@@ -28,4 +28,5 @@ public class PigxTenantConfigProperties {
* 多租户的数据表集合
*/
private List<String> tables = new ArrayList<>();
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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);
}
}
}
@@ -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();
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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();
}
}
@@ -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 {
}
@@ -39,4 +39,5 @@ public class DruidDataSourceProperties {
* 查询数据源的SQL
*/
private String queryDsSql = "select * from gen_datasource_conf where del_flag = 0";
}
@@ -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;
}
}
@@ -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]);
}
}
@@ -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 {};
}
@@ -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;
}
}
@@ -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
@@ -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 {
}
@@ -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);
}
}
@@ -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]);
}
}));
}
}
@@ -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);
}
}
@@ -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));
}
}
@@ -30,10 +30,10 @@ public interface GrayLoadBalancer {
/**
* 根据serviceId 筛选可用服务
*
* @param serviceId 服务ID
* @param request 当前请求
* @param request 当前请求
* @return
*/
ServiceInstance choose(String serviceId, ServerHttpRequest request);
}
@@ -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()));
}
}
@@ -26,7 +26,9 @@ import org.springframework.context.ApplicationEvent;
* 路由初始化事件
*/
public class DynamicRouteInitEvent extends ApplicationEvent {
public DynamicRouteInitEvent(Object source) {
super(source);
}
}
@@ -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<>();
}
@@ -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);
}
}
@@ -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) {
@@ -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;
}
@@ -46,4 +46,5 @@ public class GrayRibbonLoadBalancerConfiguration {
public RequestInterceptor grayFeignRequestInterceptor() {
return new GrayFeignRequestInterceptor();
}
}
@@ -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);
}
}
}
@@ -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()));
}
@@ -48,4 +48,5 @@ public class XxlJobAutoConfiguration {
xxlJobSpringExecutor.setLogRetentionDays(xxlJobProperties.getExecutor().getLogRetentionDays());
return xxlJobSpringExecutor;
}
}
@@ -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 {
}
@@ -27,9 +27,10 @@ import lombok.Data;
*/
@Data
public class XxlAdminProperties {
/**
* 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。
* 执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
* 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。 执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
*/
private String addresses = "http://127.0.0.1:8080/xxl-job-admin";
}
@@ -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;
}
@@ -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();
}
@@ -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);
}
}
@@ -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();
}
@@ -39,6 +39,7 @@ import org.springframework.context.ApplicationEventPublisher;
@Aspect
@AllArgsConstructor
public class SysLogAspect {
private final ApplicationEventPublisher publisher;
@SneakyThrows
@@ -24,11 +24,12 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* 系统日志事件
* @author lengleng 系统日志事件
*/
@Getter
@AllArgsConstructor
public class SysLogEvent {
private final SysLog sysLog;
}
@@ -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);
}
}
@@ -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));
}
}
@@ -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() {
@@ -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
@@ -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;
@@ -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,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();
}
}
@@ -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 {
}
@@ -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