parent
7d22c92122
commit
f94009e2c4
@ -0,0 +1,22 @@ |
||||
package com.gitee.sop.bookweb.config; |
||||
|
||||
import com.gitee.sop.servercommon.configuration.AlipayServiceConfiguration; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* 使用支付宝开放平台功能 |
||||
* @author tanghc |
||||
*/ |
||||
@Configuration |
||||
public class OpenServiceConfig extends AlipayServiceConfiguration { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 使用淘宝开放平台功能 |
||||
* @author tanghc |
||||
*/ |
||||
//@Configuration
|
||||
//public class OpenServiceConfig extends TaobaoServiceConfiguration {
|
||||
//
|
||||
//}
|
@ -0,0 +1,40 @@ |
||||
package com.gitee.sop.bookweb.controller; |
||||
|
||||
import com.gitee.sop.bookweb.consumer.StoryServiceConsumer; |
||||
import com.gitee.sop.servercommon.annotation.ApiMapping; |
||||
import com.gitee.sop.story.api.domain.Story; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* 支付宝服务端,假设签名验证通过后,到达这里进行具体的业务处理。 |
||||
* 这里演示如何接受业务参数。 |
||||
* @author tanghc |
||||
*/ |
||||
@RestController |
||||
public class AlipayBookController { |
||||
|
||||
@Autowired |
||||
StoryServiceConsumer storyServiceConsumer; |
||||
|
||||
@ApiMapping(value = "alipay.book.get") |
||||
public Story getBook() { |
||||
Story story = new Story(); |
||||
story.setId(1); |
||||
story.setName("白雪公主(alipay.book.get)"); |
||||
return story; |
||||
} |
||||
|
||||
// 调用story服务
|
||||
@ApiMapping(value = "alipay.book.story.get") |
||||
public Object getBook2() { |
||||
Story story = new Story(); |
||||
story.setId(1); |
||||
story.setName("白雪公主(alipay.book.story.get)"); |
||||
Story story2 = storyServiceConsumer.getStory(1); |
||||
return Arrays.asList(story, story2); |
||||
} |
||||
|
||||
} |
@ -1,6 +0,0 @@ |
||||
server.port=3333 |
||||
spring.application.name=book-service |
||||
eureka.host=localhost |
||||
eureka.port=1111 |
||||
eureka.client.serviceUrl.defaultZone=http://${eureka.host}:${eureka.port}/eureka/ |
||||
|
@ -0,0 +1,9 @@ |
||||
server: |
||||
port: 3333 |
||||
|
||||
eureka: |
||||
port: 1111 |
||||
host: localhost |
||||
client: |
||||
serviceUrl: |
||||
defaultZone: http://${eureka.host}:${eureka.port}/eureka/ |
@ -0,0 +1,7 @@ |
||||
spring: |
||||
application: |
||||
name: book-service |
||||
|
||||
cloud: |
||||
zookeeper: |
||||
connect-string: localhost:2181 |
@ -0,0 +1,38 @@ |
||||
package com.gitee.sop.gatewaycommon.bean; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.HashSet; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.function.Consumer; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public abstract class ServiceRouteRepository<R, E> { |
||||
/** |
||||
* key:serviceId |
||||
*/ |
||||
private Map<String, Set<E>> serviceRouteMap = new ConcurrentHashMap<>(); |
||||
|
||||
public abstract String getServiceId(R r); |
||||
|
||||
public void saveRouteDefinition(R serviceRouteInfo, E definition) { |
||||
String serverId = getServiceId(serviceRouteInfo); |
||||
Set<E> routeDefinitionSet = serviceRouteMap.putIfAbsent(serverId, new HashSet<>(16)); |
||||
if (routeDefinitionSet == null) { |
||||
routeDefinitionSet = serviceRouteMap.get(serverId); |
||||
} |
||||
routeDefinitionSet.add(definition); |
||||
} |
||||
|
||||
public synchronized void deleteAll(R serviceRouteInfo, Consumer<E> consumer) { |
||||
String serverId = getServiceId(serviceRouteInfo); |
||||
Set<E> definitionSet = serviceRouteMap.getOrDefault(serverId, Collections.emptySet()); |
||||
for (E routeDefinition : definitionSet) { |
||||
consumer.accept(routeDefinition); |
||||
} |
||||
definitionSet.clear(); |
||||
} |
||||
} |
@ -1,74 +1,123 @@ |
||||
package com.gitee.sop.gatewaycommon.gateway.route; |
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ServiceRouteRepository; |
||||
import com.gitee.sop.gatewaycommon.manager.RouteRepository; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.beans.factory.BeanFactory; |
||||
import org.springframework.beans.factory.BeanFactoryAware; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.cloud.gateway.event.PredicateArgsEvent; |
||||
import org.springframework.cloud.gateway.event.RefreshRoutesEvent; |
||||
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; |
||||
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory; |
||||
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository; |
||||
import org.springframework.cloud.gateway.route.RouteDefinition; |
||||
import org.springframework.cloud.gateway.route.RouteDefinitionRepository; |
||||
import org.springframework.cloud.gateway.support.NotFoundException; |
||||
import org.springframework.cloud.gateway.support.ConfigurationUtils; |
||||
import org.springframework.context.ApplicationEventPublisher; |
||||
import org.springframework.context.ApplicationEventPublisherAware; |
||||
import org.springframework.http.ResponseEntity; |
||||
import org.springframework.core.convert.ConversionService; |
||||
import org.springframework.expression.spel.standard.SpelExpressionParser; |
||||
import org.springframework.validation.Validator; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.HashSet; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
/** |
||||
* 动态更新路由 |
||||
* 路由存储管理,负责动态更新路由 |
||||
* |
||||
* @author thc |
||||
*/ |
||||
@Slf4j |
||||
public class GatewayRouteRepository implements ApplicationEventPublisherAware, RouteRepository<RouteDefinition> { |
||||
public class GatewayRouteRepository extends InMemoryRouteDefinitionRepository |
||||
implements ApplicationEventPublisherAware, |
||||
BeanFactoryAware, |
||||
RouteRepository<GatewayServiceRouteInfo, RouteDefinition> { |
||||
|
||||
private final SpelExpressionParser parser = new SpelExpressionParser(); |
||||
|
||||
private ServiceRouteRepository<GatewayServiceRouteInfo, RouteDefinition> serviceRouteRepository = new ServiceRouteRepository<GatewayServiceRouteInfo, RouteDefinition>() { |
||||
@Override |
||||
public String getServiceId(GatewayServiceRouteInfo serviceRouteInfo) { |
||||
return serviceRouteInfo.getAppName(); |
||||
} |
||||
}; |
||||
|
||||
@Autowired |
||||
private RouteDefinitionRepository routeDefinitionRepository; |
||||
private ConversionService conversionService; |
||||
|
||||
@Autowired |
||||
private Validator validator; |
||||
|
||||
private ApplicationEventPublisher publisher; |
||||
|
||||
/** 根据ID获取路由 */ |
||||
private BeanFactory beanFactory; |
||||
|
||||
/** |
||||
* 根据ID获取路由 |
||||
*/ |
||||
@Override |
||||
public RouteDefinition get(String id) { |
||||
return routeDefinitionRepository.getRouteDefinitions() |
||||
return getRouteDefinitions() |
||||
.filter(routeDefinition -> { |
||||
return routeDefinition.getId().equals(id); |
||||
}).blockFirst(); |
||||
} |
||||
|
||||
/** 增加路由 */ |
||||
/** |
||||
* 增加路由 |
||||
*/ |
||||
@Override |
||||
public String add(RouteDefinition definition) { |
||||
routeDefinitionRepository.save(Mono.just(definition)).subscribe(); |
||||
public String add(GatewayServiceRouteInfo serviceRouteInfo, RouteDefinition definition) { |
||||
super.save(Mono.just(definition)).subscribe(); |
||||
serviceRouteRepository.saveRouteDefinition(serviceRouteInfo, definition); |
||||
this.initPredicateDefinition(definition); |
||||
this.publisher.publishEvent(new RefreshRoutesEvent(this)); |
||||
return "success"; |
||||
} |
||||
|
||||
/** 更新路由 */ |
||||
@Override |
||||
public String update(RouteDefinition definition) { |
||||
log.info("更新route,id:{}", definition.getId()); |
||||
try { |
||||
this.routeDefinitionRepository.delete(Mono.just(definition.getId())); |
||||
} catch (Exception e) { |
||||
return "update fail,not find route routeId: " + definition.getId(); |
||||
} |
||||
try { |
||||
routeDefinitionRepository.save(Mono.just(definition)).subscribe(); |
||||
this.publisher.publishEvent(new RefreshRoutesEvent(this)); |
||||
return "success"; |
||||
} catch (Exception e) { |
||||
return "update route fail"; |
||||
protected void initPredicateDefinition(RouteDefinition definition) { |
||||
for (PredicateDefinition predicate : definition.getPredicates()) { |
||||
Map<String, String> args = predicate.getArgs(); |
||||
if (!args.isEmpty()) { |
||||
RoutePredicateFactory<NameVersionRoutePredicateFactory.Config> factory = new NameVersionRoutePredicateFactory(); |
||||
Map<String, Object> properties = factory.shortcutType().normalize(args, factory, this.parser, this.beanFactory); |
||||
Object config = factory.newConfig(); |
||||
ConfigurationUtils.bind(config, properties, factory.shortcutFieldPrefix(), predicate.getName(), |
||||
validator, conversionService); |
||||
this.publisher.publishEvent(new PredicateArgsEvent(this, definition.getId(), properties)); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
/** 删除路由 */ |
||||
/** |
||||
* 删除路由 |
||||
*/ |
||||
@Override |
||||
public void delete(String id) { |
||||
this.routeDefinitionRepository.delete(Mono.just(id)) |
||||
.then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build()))) |
||||
.onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build())); |
||||
super.delete(Mono.just(id)); |
||||
this.publisher.publishEvent(new PredicateArgsEvent(this, id, Collections.emptyMap())); |
||||
} |
||||
|
||||
@Override |
||||
public void deleteAll(GatewayServiceRouteInfo serviceRouteInfo) { |
||||
serviceRouteRepository.deleteAll(serviceRouteInfo, routeDefinition -> { |
||||
this.delete(routeDefinition.getId()); |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { |
||||
this.publisher = applicationEventPublisher; |
||||
} |
||||
|
||||
@Override |
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException { |
||||
this.beanFactory = beanFactory; |
||||
} |
||||
} |
@ -0,0 +1,23 @@ |
||||
package com.gitee.sop.gatewaycommon.util; |
||||
|
||||
import org.springframework.cloud.gateway.route.Route; |
||||
|
||||
import java.net.URI; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class RoutePathUtil { |
||||
|
||||
public static final String REGEX = "\\#"; |
||||
|
||||
public static String findPath(String uri) { |
||||
// #后面是对应的path
|
||||
String[] uriArr = uri.split(REGEX); |
||||
if (uriArr.length == 2) { |
||||
return uriArr[1]; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -1,41 +0,0 @@ |
||||
package com.gitee.sop.gatewaycommon.zuul.filter; |
||||
|
||||
import com.gitee.sop.gatewaycommon.message.ErrorEnum; |
||||
import com.netflix.zuul.context.RequestContext; |
||||
import com.netflix.zuul.exception.ZuulException; |
||||
import org.apache.commons.lang.StringUtils; |
||||
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class PreTokenFilter extends BaseZuulFilter { |
||||
|
||||
@Override |
||||
protected FilterType getFilterType() { |
||||
return FilterType.PRE; |
||||
} |
||||
|
||||
@Override |
||||
protected int getFilterOrder() { |
||||
return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1; |
||||
} |
||||
|
||||
@Override |
||||
protected Object doRun(RequestContext ctx) throws ZuulException { |
||||
Object serviceId = ctx.get(FilterConstants.SERVICE_ID_KEY); |
||||
log.info("serviceId:{}", serviceId); |
||||
HttpServletRequest request = ctx.getRequest(); |
||||
|
||||
log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString()); |
||||
|
||||
String accessToken = request.getParameter("access_token"); |
||||
if (StringUtils.isBlank(accessToken)) { |
||||
throw ErrorEnum.AOP_INVALID_APP_AUTH_TOKEN.getErrorMeta().getException(); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,45 @@ |
||||
package com.gitee.sop.gateway.config; |
||||
|
||||
import com.gitee.sop.gatewaycommon.bean.ApiContext; |
||||
import com.gitee.sop.gatewaycommon.zuul.configuration.AlipayZuulConfiguration; |
||||
import com.gitee.sop.gatewaycommon.zuul.configuration.TaobaoZuulConfiguration; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 使用Spring Cloud Zuul,推荐使用 |
||||
* |
||||
* 注意:下面两个只能使用一个 |
||||
*/ |
||||
|
||||
/** |
||||
* 开通支付宝开放平台能力 |
||||
* @author tanghc |
||||
*/ |
||||
@Configuration |
||||
public class ZuulConfig extends AlipayZuulConfiguration { |
||||
|
||||
{ |
||||
Map<String, String> appSecretStore = new HashMap(); |
||||
appSecretStore.put("alipay_test", "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlyb9aUBaljQP/vjmBFe1mF8HsWSvyfC2NTlpT/V9E+sBxTr8TSkbzJCeeeOEm4LCaVXL0Qz63MZoT24v7AIXTuMdj4jyiM/WJ4tjrWAgnmohNOegfntTto16C3l234vXz4ryWZMR/7W+MXy5B92wPGQEJ0LKFwNEoLspDEWZ7RdE53VH7w6y6sIZUfK+YkXWSwehfKPKlx+lDw3zRJ3/yvMF+U+BAdW/MfECe1GuBnCFKnlMRh3UKczWyXWkL6ItOpYHHJi/jx85op5BWDje2pY9QowzfN94+0DB3T7UvZeweu3zlP6diwAJDzLaFQX8ULfWhY+wfKxIRgs9NoiSAQIDAQAB"); |
||||
ApiContext.getApiConfig().addAppSecret(appSecretStore); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 开通支付宝开放平台能力 |
||||
* @author tanghc |
||||
*/ |
||||
//@Configuration
|
||||
//public class ZuulConfig extends TaobaoZuulConfiguration {
|
||||
//
|
||||
// {
|
||||
// Map<String, String> appSecretStore = new HashMap();
|
||||
// appSecretStore.put("taobao_test", "G9w0BAQEFAAOCAQ8AMIIBCgKCA");
|
||||
// ApiContext.getApiConfig().addAppSecret(appSecretStore);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
@ -1,7 +0,0 @@ |
||||
server.port=2222 |
||||
spring.application.name=story-service |
||||
|
||||
eureka.host=localhost |
||||
eureka.port=1111 |
||||
eureka.client.serviceUrl.defaultZone=http://${eureka.host}:${eureka.port}/eureka/ |
||||
|
@ -0,0 +1,9 @@ |
||||
server: |
||||
port: 2222 |
||||
|
||||
eureka: |
||||
port: 1111 |
||||
host: localhost |
||||
client: |
||||
serviceUrl: |
||||
defaultZone: http://${eureka.host}:${eureka.port}/eureka/ |
Loading…
Reference in new issue