建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
简单版参照
https://blog.csdn.net/u010102390/article/details/80179754
看下spring-security-oauth2是怎么玩的
1.首先定义总的Configurer类--ClientDetailsServiceConfigurer 。 友情提示,所有生成配置的类都是以Configurer结尾。
此类持有ClientDetailsServiceBuilder ,ClientDetailsServiceBuilder的子类负责通过ClientBuilder创建Client
/**
* @author Rob Winch
*
*/
public class ClientDetailsServiceConfigurer extends
SecurityConfigurerAdapter> {
public ClientDetailsServiceConfigurer(ClientDetailsServiceBuilder> builder) {
setBuilder(builder);
}
public ClientDetailsServiceBuilder> withClientDetails(ClientDetailsService clientDetailsService) throws Exception {
setBuilder(getBuilder().clients(clientDetailsService));
return this.and();
}
public InMemoryClientDetailsServiceBuilder inMemory() throws Exception {
InMemoryClientDetailsServiceBuilder next = getBuilder().inMemory();
setBuilder(next);
return next;
}
public JdbcClientDetailsServiceBuilder jdbc(DataSource dataSource) throws Exception {
JdbcClientDetailsServiceBuilder next = getBuilder().jdbc().dataSource(dataSource);
setBuilder(next);
return next;
}
@Override
public void init(ClientDetailsServiceBuilder> builder) throws Exception {
}
@Override
public void configure(ClientDetailsServiceBuilder> builder) throws Exception {
}
}
以InMemoryClientDetailsServiceBuilder为例
public class InMemoryClientDetailsServiceBuilder extends
ClientDetailsServiceBuilder {
private Map clientDetails = new HashMap();
@Override
protected void addClient(String clientId, ClientDetails value) {
clientDetails.put(clientId, value);
}
@Override
protected ClientDetailsService performBuild() {
InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService();
clientDetailsService.setClientDetailsStore(clientDetails);
return clientDetailsService;
}
}
继承ClientDetailsServiceBuilder
持有private List
public class ClientDetailsServiceBuilder> extends
SecurityConfigurerAdapter implements SecurityBuilder {
private List clientBuilders = new ArrayList();
public InMemoryClientDetailsServiceBuilder inMemory() throws Exception {
return new InMemoryClientDetailsServiceBuilder();
}
public JdbcClientDetailsServiceBuilder jdbc() throws Exception {
return new JdbcClientDetailsServiceBuilder();
}
@SuppressWarnings("rawtypes")
public ClientDetailsServiceBuilder> clients(final ClientDetailsService clientDetailsService) throws Exception {
return new ClientDetailsServiceBuilder() {
@Override
public ClientDetailsService build() throws Exception {
return clientDetailsService;
}
};
}
//设置Client并把其放到list
public ClientBuilder withClient(String clientId) {
ClientBuilder clientBuilder = new ClientBuilder(clientId);
this.clientBuilders.add(clientBuilder);
return clientBuilder;
}
。。。。。。。。。。。。。。。
}
ClientBuilder 配置组装client, 是内部类
public final class ClientBuilder {
private final String clientId;
private Collection authorizedGrantTypes = new LinkedHashSet();
private Collection authorities = new LinkedHashSet();
private Integer accessTokenValiditySeconds;
private Integer refreshTokenValiditySeconds;
private Collection scopes = new LinkedHashSet();
private Collection autoApproveScopes = new HashSet();
private String secret;
private Set registeredRedirectUris = new HashSet();
private Set resourceIds = new HashSet();
private boolean autoApprove;
private Map additionalInformation = new LinkedHashMap();
private ClientDetails build() {
BaseClientDetails result = new BaseClientDetails();
result.setClientId(clientId);
result.setAuthorizedGrantTypes(authorizedGrantTypes);
result.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
result.setRefreshTokenValiditySeconds(refreshTokenValiditySeconds);
result.setRegisteredRedirectUri(registeredRedirectUris);
result.setClientSecret(secret);
result.setScope(scopes);
result.setAuthorities(AuthorityUtils.createAuthorityList(authorities.toArray(new String[authorities.size()])));
result.setResourceIds(resourceIds);
result.setAdditionalInformation(additionalInformation);
if (autoApprove) {
result.setAutoApproveScopes(scopes);
}
else {
result.setAutoApproveScopes(autoApproveScopes);
}
return result;
}
public ClientBuilder resourceIds(String... resourceIds) {
for (String resourceId : resourceIds) {
this.resourceIds.add(resourceId);
}
return this;
}
public ClientBuilder redirectUris(String... registeredRedirectUris) {
for (String redirectUri : registeredRedirectUris) {
this.registeredRedirectUris.add(redirectUri);
}
return this;
}
public ClientBuilder authorizedGrantTypes(String... authorizedGrantTypes) {
for (String grant : authorizedGrantTypes) {
this.authorizedGrantTypes.add(grant);
}
return this;
}
public ClientBuilder accessTokenValiditySeconds(int accessTokenValiditySeconds) {
this.accessTokenValiditySeconds = accessTokenValiditySeconds;
return this;
}
public ClientBuilder refreshTokenValiditySeconds(int refreshTokenValiditySeconds) {
this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
return this;
}
public ClientBuilder secret(String secret) {
this.secret = secret;
return this;
}
public ClientBuilder scopes(String... scopes) {
for (String scope : scopes) {
this.scopes.add(scope);
}
return this;
}
public ClientBuilder authorities(String... authorities) {
for (String authority : authorities) {
this.authorities.add(authority);
}
return this;
}
public ClientBuilder autoApprove(boolean autoApprove) {
this.autoApprove = autoApprove;
return this;
}
public ClientBuilder autoApprove(String... scopes) {
for (String scope : scopes) {
this.autoApproveScopes.add(scope);
}
return this;
}
public ClientBuilder additionalInformation(Map map) {
this.additionalInformation.putAll(map);
return this;
}
public ClientBuilder additionalInformation(String... pairs) {
for (String pair : pairs) {
String separator = ":";
if (!pair.contains(separator) && pair.contains("=")) {
separator = "=";
}
int index = pair.indexOf(separator);
String key = pair.substring(0, index > 0 ? index : pair.length());
String value = index > 0 ? pair.substring(index+1) : null;
this.additionalInformation.put(key, (Object) value);
}
return this;
}
public ClientDetailsServiceBuilder and() {
return ClientDetailsServiceBuilder.this;
}
private ClientBuilder(String clientId) {
this.clientId = clientId;
}
}
4. ClientDetailsServiceConfiguration 依据配置创建ClientDetailsService
@Configuration
public class ClientDetailsServiceConfiguration {
@SuppressWarnings("rawtypes")
private ClientDetailsServiceConfigurer configurer = new ClientDetailsServiceConfigurer(new ClientDetailsServiceBuilder());
@Bean
public ClientDetailsServiceConfigurer clientDetailsServiceConfigurer() {
return configurer;
}
@Bean
@Lazy
@Scope(proxyMode=ScopedProxyMode.INTERFACES)
public ClientDetailsService clientDetailsService() throws Exception {
return configurer.and().build();
}
}
看下build方法
public class ClientDetailsServiceBuilder> extends
SecurityConfigurerAdapter implements SecurityBuilder {
private List clientBuilders = new ArrayList();
.................................................................
@Override
public ClientDetailsService build() throws Exception {
for (ClientBuilder clientDetailsBldr : clientBuilders) {
addClient(clientDetailsBldr.clientId, clientDetailsBldr.build());
}
return performBuild();
}
....................................................................
}
看下类图
好了,看一下实际代码中, 我们是怎么用它的.
@Configuration
@EnableAuthorizationServer
public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
@Autowired
private ClientService clientService;
/**
* 配置能sso登陆的客户端
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//放在内存
InMemoryClientDetailsServiceBuilder builder = clients.inMemory();
//获取所有client
List list=clientService.findAll();
for(Client config:list) {
String scopesStr=ClientDeafaultConstant.SCOPES;;
String authorizedGrantTypesStr=null;
Long accessTokenValiditySeconds=3600L;
if(!StringsUtils.hasText(authorizedGrantTypesStr)) {
authorizedGrantTypesStr=ClientDeafaultConstant.AUTHORIZED_GRANT_TYPES;
}else {
authorizedGrantTypesStr=config.getAuthorizedGrantTypes();
}
if(0==config.getAccessTokenValiditySeconds()) {
accessTokenValiditySeconds=ClientDeafaultConstant.ACCESSTOKEN_VAILDITY_SECONDS;
}else {
accessTokenValiditySeconds=config.getAccessTokenValiditySeconds();
}
String[] authorizedGrantTypes=StringUtils.splitByWholeSeparatorPreserveAllTokens(authorizedGrantTypesStr, StringsUtils.COMMA);
String[] scopes=StringUtils.splitByWholeSeparatorPreserveAllTokens(scopesStr,StringsUtils.COMMA);
//构建client信息
builder.withClient(config.getClientKey())
.secret(config.getClientSecret())
.accessTokenValiditySeconds(accessTokenValiditySeconds.intValue())
.authorizedGrantTypes(authorizedGrantTypes)
.autoApprove(true)
.scopes(scopes);
}
}
..........................................................
}