作者:付政委
人之学也,或失则多,或失则寡,或失则易,或失则止
微信公众号:bugstack虫洞栈 沉淀、分享、成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获。目前已完成的专题有;Netty4.x实战专题案例、用Java实现JVM、基于JavaAgent的全链路监控、手写RPC框架、架构设计专题案例[Ing]等。
在实际的业务开发中不只是将路由配置放到文件中,而是需要进行动态管理并且可以在变化时不用重启系统就可以更新。与此同时还需要在接口访问的时候,可以增加一些权限验证以防止恶意访问。
1itstack-demo-springcloud-08
2├── itstack-demo-springcloud-eureka-client
3│ └── src
4│ └── main
5│ ├── java
6│ │ └── org.itstack.demo
7│ │ ├── web
8│ │ │ └── EurekaClientController.java
9│ │ └── EurekaClientApplication.java
10│ └── resources
11│ └── application.yml
12├── itstack-demo-springcloud-eureka-server
13│ └── src
14│ └── main
15│ ├── java
16│ │ └── org.itstack.demo
17│ │ └── EurekaServerApplication.java
18│ └── resources
19│ └── application.yml
20├── itstack-demo-springcloud-hystrix-feign
21│ └── src
22│ └── main
23│ ├── java
24│ │ └── org.itstack.demo
25│ │ ├── service
26│ │ │ ├── hystrix
27│ │ │ │ └── FeignServiceHystrix.java
28│ │ │ └── FeignService.java
29│ │ ├── web
30│ │ │ └── FeignController.java
31│ │ └── FeignApplication.java
32│ └── resources
33│ └── application.yml
34├── itstack-demo-springcloud-hystrix-ribbon
35│ └── src
36│ └── main
37│ ├── java
38│ │ └── org.itstack.demo
39│ │ ├── service
40│ │ │ └── RibbonService.java
41│ │ ├── web
42│ │ │ └── RibbonController.java
43│ │ └── RibbonApplication.java
44│ └── resources
45│ └── application.yml
46└── itstack-demo-springcloud-zuul
47 └── src
48 └── main
49 ├── java
50 │ └── org.itstack.demo
51 │ ├── config
52 │ │ └── ZuulConfig.java
53 │ ├── filter
54 │ │ └── TokenFilter.java
55 │ ├── router
56 │ │ └── RouteLocator.java
57 │ ├── service
58 │ │ └── RefreshRouteService.java
59 │ └── ZuulApplication.java
60 └── resources
61 └── application.yml
完整代码欢迎关注公众号:bugstack虫洞栈 回复“SpringCloud专题”进行下载
itstack-demo-springcloud-zuul & 动态路由与权限过滤
config/ZuulConfig.java & 路由配置类
1/**
2 * 路由配置
3 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例
4 * 论坛:http://bugstack.cn
5 * Create by 付政委 on @2019
6 */
7@Configuration
8public class ZuulConfig {
9
10 @Autowired
11 private ZuulProperties zuulProperties;
12 @Autowired
13 private ServerProperties server;
14
15 @Bean
16 public RouteLocator routeLocator() {
17 return new RouteLocator(this.server.getServlet().getPath(), this.zuulProperties);
18 }
19
20}
filter/TokenFilter.java & 权限校验类
1/**
2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例
3 * 论坛:http://bugstack.cn
4 * Create by 付政委 on @2019
5 */
6public class TokenFilter extends ZuulFilter {
7
8 /**
9 * 过滤器的类型,它决定过滤器在请求的哪个生命周期中执行。
10 * FilterConstants.PRE_TYPE:代表会在请求被路由之前执行。
11 * PRE、ROUTING、POST、ERROR
12 */
13 public String filterType() {
14 return FilterConstants.PRE_TYPE;
15 }
16
17 /**
18 * filter执行顺序,通过数字指定。[数字越大,优先级越低]
19 */
20 public int filterOrder() {
21 return 0;
22 }
23
24 /**
25 * 判断该过滤器是否需要被执行。这里我们直接返回了true,因此该过滤器对所有请求都会生效。
26 * 实际运用中我们可以利用该函数来指定过滤器的有效范围。
27 */
28 public boolean shouldFilter() {
29 return true;
30 }
31
32 /*
33 * 具体执行逻辑
34 */
35 public Object run() {
36 RequestContext ctx = RequestContext.getCurrentContext();
37 HttpServletRequest request = ctx.getRequest();
38 String token = request.getParameter("token");
39 if (token == null || token.isEmpty()) {
40 ctx.setSendZuulResponse(false);
41 ctx.setResponseStatusCode(401);
42 ctx.setResponseBody("refuse! token is empty");
43 }
44 return null;
45 }
46
47}
router/RouteLocator.java & 路由类
1/**
2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例
3 * 论坛:http://bugstack.cn
4 * Create by 付政委 on @2019
5 */
6public class RouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
7
8 private ZuulProperties properties;
9
10 public RouteLocator(String servletPath, ZuulProperties properties) {
11 super(servletPath, properties);
12 this.properties = properties;
13 }
14
15 @Override
16 public void refresh() {
17 doRefresh();
18 }
19
20 @Override
21 protected Map<String, ZuulRoute> locateRoutes() {
22 LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<String, ZuulRoute>();
23 //从application.properties中加载路由信息
24 routesMap.putAll(super.locateRoutes());
25 //从db中加载路由信息
26 routesMap.putAll(routesConfigGroup());
27 //优化一下配置
28 LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();
29 for (Map.Entry<String, ZuulRoute> entry : routesMap.entrySet()) {
30 String path = entry.getKey();
31 // Prepend with slash if not already present.
32 if (!path.startsWith("/")) {
33 path = "/" + path;
34 }
35 if (StringUtils.hasText(this.properties.getPrefix())) {
36 path = this.properties.getPrefix() + path;
37 if (!path.startsWith("/")) {
38 path = "/" + path;
39 }
40 }
41 values.put(path, entry.getValue());
42 }
43 return values;
44 }
45
46 /**
47 * 路由配置组,可以从数据库中读取
48 * 基本配置与写在文件中配置类似,如下;
49 * # routes:
50 * # api-a:
51 * # path: /route-a/**
52 * # serviceId: itstack-demo-springcloud-feign
53 * # api-b:
54 * # path: /route-b/**
55 * # serviceId: itstack-demo-springcloud-ribbon
56 * @return 配置组内容
57 */
58 private Map<String, ZuulRoute> routesConfigGroup() {
59 Map<String, ZuulRoute> routes = new LinkedHashMap<>();
60
61 ZuulRoute zuulRoute = new ZuulRoute();
62 zuulRoute.setId("route-a");
63 zuulRoute.setPath("/route-a/**");
64 zuulRoute.setServiceId("itstack-demo-springcloud-feign");
65 // 如果使用了注册中心,那么可以根据serviceId进行访问。
66 // zuulRoute.setUrl("http://localhost:9001");
67 zuulRoute.setRetryable(false);
68 zuulRoute.setStripPrefix(true);
69 zuulRoute.setSensitiveHeaders(new HashSet<>());
70
71 routes.put(zuulRoute.getPath(), zuulRoute);
72
73 return routes;
74 }
75
76}
service/RefreshRouteService.java & 路由刷新服务
1/**
2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例
3 * 论坛:http://bugstack.cn
4 * Create by 付政委 on @2019
5 */
6@Service
7public class RefreshRouteService {
8
9 @Autowired
10 private ApplicationEventPublisher publisher;
11
12 @Autowired
13 private RouteLocator routeLocator;
14
15 public void refreshRoute() {
16 RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(routeLocator);
17 publisher.publishEvent(routesRefreshedEvent);
18 }
19
20}
ZuulApplication.java & 启动服务注意注解,另外提供了服务接口
1/**
2 * 微信公众号:bugstack虫洞栈 | 专注原创技术专题案例
3 * 论坛:http://bugstack.cn
4 * Create by 付政委 on @2019
5 */
6@SpringBootApplication
7@EnableZuulProxy
8@EnableEurekaClient
9@EnableDiscoveryClient
10@RestController
11public class ZuulApplication {
12
13 public static void main(String[] args) {
14 SpringApplication.run(ZuulApplication.class, args);
15 }
16
17 @Bean
18 public TokenFilter tokenFilter() {
19 return new TokenFilter();
20 }
21
22 @Autowired
23 private RefreshRouteService refreshRouteService;
24 @Autowired
25 private ZuulHandlerMapping zuulHandlerMapping;
26
27 @RequestMapping("api/refresh")
28 public String refresh(){
29 refreshRouteService.refreshRoute();
30 return "success";
31 }
32
33 @RequestMapping("api/queryRouteInfo")
34 @ResponseBody
35 public Map<String, Object> queryRouteInfo(){
36 return zuulHandlerMapping.getHandlerMap();
37 }
38
39}
application.yml & 配置文件修改,路由过滤
1server:
2 port: 10001
3
4spring:
5 application:
6 name: itstack-demo-ddd-zuul
7
8eureka:
9 client:
10 serviceUrl:
11 defaultZone: http://localhost:7397/eureka/
12
13# 动态路由,以下配置注释;
14# http://localhost:10001/route-a/api/queryUserInfo?userId=111
15# http://localhost:10001/route-b/api/queryUserInfo?userId=111
16zuul:
17 ignoredPatterns: /api/**
18# routes:
19# api-a:
20# path: /route-a/**
21# serviceId: itstack-demo-springcloud-feign
22# api-b:
23# path: /route-b/**
24# serviceId: itstack-demo-springcloud-ribbon
25
java<br /> Hi 微信公众号:bugstack虫洞栈 | 111 >: from eureka client port: 8001 From Feign<br />