正在显示
16 个修改的文件
包含
860 行增加
和
0 行删除
pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
3 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
4 | + <modelVersion>4.0.0</modelVersion> | ||
5 | + <packaging>jar</packaging> | ||
6 | + <parent> | ||
7 | + <groupId>org.springframework.boot</groupId> | ||
8 | + <artifactId>spring-boot-starter-parent</artifactId> | ||
9 | + <version>2.1.8.RELEASE</version> | ||
10 | + <relativePath/> <!-- lookup parent from repository --> | ||
11 | + </parent> | ||
12 | + <groupId>com.example</groupId> | ||
13 | + <artifactId>gateway</artifactId> | ||
14 | + <version>0.0.1-SNAPSHOT</version> | ||
15 | + <name>gateway</name> | ||
16 | + <description>gateway project for Spring Boot</description> | ||
17 | + | ||
18 | + <properties> | ||
19 | + <java.version>1.8</java.version> | ||
20 | + <spring-cloud.version>Greenwich.SR2</spring-cloud.version> | ||
21 | + </properties> | ||
22 | + | ||
23 | + <dependencies> | ||
24 | + <dependency> | ||
25 | + <groupId>org.springframework.cloud</groupId> | ||
26 | + <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> | ||
27 | + </dependency> | ||
28 | + <dependency> | ||
29 | + <groupId>org.springframework.cloud</groupId> | ||
30 | + <artifactId>spring-cloud-starter-gateway</artifactId> | ||
31 | + </dependency> | ||
32 | + <dependency> | ||
33 | + <groupId>org.springframework.boot</groupId> | ||
34 | + <artifactId>spring-boot-starter-data-redis</artifactId> | ||
35 | + </dependency> | ||
36 | + <dependency> | ||
37 | + <groupId>org.springframework.boot</groupId> | ||
38 | + <artifactId>spring-boot-starter-actuator</artifactId> | ||
39 | + </dependency> | ||
40 | + <dependency> | ||
41 | + <groupId>org.projectlombok</groupId> | ||
42 | + <artifactId>lombok</artifactId> | ||
43 | + <version>1.18.8</version> | ||
44 | + </dependency> | ||
45 | + <dependency> | ||
46 | + <groupId>com.alibaba</groupId> | ||
47 | + <artifactId>fastjson</artifactId> | ||
48 | + <version>1.2.49</version> | ||
49 | + </dependency> | ||
50 | + </dependencies> | ||
51 | + | ||
52 | + <dependencyManagement> | ||
53 | + <dependencies> | ||
54 | + <dependency> | ||
55 | + <groupId>org.springframework.cloud</groupId> | ||
56 | + <artifactId>spring-cloud-dependencies</artifactId> | ||
57 | + <version>${spring-cloud.version}</version> | ||
58 | + <type>pom</type> | ||
59 | + <scope>import</scope> | ||
60 | + </dependency> | ||
61 | + </dependencies> | ||
62 | + </dependencyManagement> | ||
63 | + | ||
64 | + <build> | ||
65 | + <plugins> | ||
66 | + <plugin> | ||
67 | + <groupId>org.springframework.boot</groupId> | ||
68 | + <artifactId>spring-boot-maven-plugin</artifactId> | ||
69 | + </plugin> | ||
70 | + <!--复制jar包到指定目录--> | ||
71 | + <plugin> | ||
72 | + <artifactId>maven-antrun-plugin</artifactId> | ||
73 | + <executions> | ||
74 | + <execution> | ||
75 | + <id>gateway</id> | ||
76 | + <phase>package</phase> | ||
77 | + <configuration> | ||
78 | + <tasks> | ||
79 | + <copy todir="docker" file="target/${project.artifactId}-${project.version}.${project.packaging}" /> | ||
80 | + </tasks> | ||
81 | + </configuration> | ||
82 | + <goals> | ||
83 | + <goal>run</goal> | ||
84 | + </goals> | ||
85 | + </execution> | ||
86 | + </executions> | ||
87 | + </plugin> | ||
88 | + </plugins> | ||
89 | + </build> | ||
90 | + | ||
91 | +</project> |
1 | +package com.example.gateway; | ||
2 | + | ||
3 | +import org.springframework.boot.SpringApplication; | ||
4 | +import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
5 | +import org.springframework.cloud.client.loadbalancer.LoadBalanced; | ||
6 | +import org.springframework.context.annotation.Bean; | ||
7 | +import org.springframework.web.client.RestTemplate; | ||
8 | + | ||
9 | +@SpringBootApplication | ||
10 | +//@EnableScheduling | ||
11 | +public class GatewayApplication { | ||
12 | + | ||
13 | + public static void main(String[] args) { | ||
14 | + SpringApplication.run(GatewayApplication.class, args); | ||
15 | + } | ||
16 | + | ||
17 | + @Bean | ||
18 | + @LoadBalanced | ||
19 | + public RestTemplate restTemplate(){ | ||
20 | + return new RestTemplate(); | ||
21 | + } | ||
22 | + | ||
23 | +} |
1 | +package com.example.gateway.filter; | ||
2 | + | ||
3 | +import com.example.gateway.model.PERMISSION; | ||
4 | +import com.example.gateway.util.JsonToBean; | ||
5 | +import org.springframework.beans.factory.annotation.Autowired; | ||
6 | +import org.springframework.cloud.gateway.filter.GatewayFilterChain; | ||
7 | +import org.springframework.cloud.gateway.filter.GlobalFilter; | ||
8 | +import org.springframework.core.Ordered; | ||
9 | +import org.springframework.data.redis.core.StringRedisTemplate; | ||
10 | +import org.springframework.http.HttpStatus; | ||
11 | +import org.springframework.http.server.reactive.ServerHttpRequest; | ||
12 | +import org.springframework.stereotype.Component; | ||
13 | +import org.springframework.util.AntPathMatcher; | ||
14 | +import org.springframework.web.server.ServerWebExchange; | ||
15 | +import reactor.core.publisher.Mono; | ||
16 | + | ||
17 | +import java.util.List; | ||
18 | + | ||
19 | +/** | ||
20 | + * @author | ||
21 | + * @time 2019-09-09 12:13 | ||
22 | + */ | ||
23 | +@Component | ||
24 | +public class WrapperResponseGlobalFilter implements GlobalFilter, Ordered { | ||
25 | + | ||
26 | + private static final String LOGIN = "user-center/login"; | ||
27 | + | ||
28 | + @Autowired | ||
29 | + private StringRedisTemplate stringRedisTemplate; | ||
30 | + | ||
31 | + private static AntPathMatcher pathMatcher = new AntPathMatcher(); | ||
32 | + | ||
33 | + @Override | ||
34 | + public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { | ||
35 | + ServerHttpRequest request = exchange.getRequest(); | ||
36 | + if(request.getPath().toString().contains(LOGIN)){ | ||
37 | + return chain.filter(exchange); | ||
38 | + } | ||
39 | + boolean flag = UrlFilter(request); | ||
40 | + if(!flag){ | ||
41 | + exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); | ||
42 | + return exchange.getResponse().setComplete(); | ||
43 | + } | ||
44 | + | ||
45 | +// ServerHttpResponse response = exchange.getResponse(); | ||
46 | +// DataBufferFactory bufferFactory = response.bufferFactory(); | ||
47 | +// ServerHttpResponseDecorator decorator = new ServerHttpResponseDecorator(response) { | ||
48 | +// @Override | ||
49 | +// public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { | ||
50 | +// if (body instanceof Flux) { | ||
51 | +// Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body; | ||
52 | +// Publisher<? extends DataBuffer> re = fluxBody.buffer().map(dataBuffer -> { | ||
53 | +// StringBuffer stringBuffer = new StringBuffer(); | ||
54 | +// dataBuffer.forEach(i -> { | ||
55 | +// byte[] content = new byte[i.readableByteCount()]; | ||
56 | +// i.read(content); | ||
57 | +// DataBufferUtils.release(i); | ||
58 | +// stringBuffer.append(new String(content, Charset.forName("utf-8"))); | ||
59 | +// }); | ||
60 | +// if (flag) { | ||
61 | +// byte[] uppedContent = stringBuffer.toString().getBytes(); | ||
62 | +// return bufferFactory.wrap(uppedContent); | ||
63 | +// } else { | ||
64 | +// ResponseBean responseBean = new ResponseBean("401", "身份认证失败,或者权限不足", "", new ArrayList(), ""); | ||
65 | +// String json = JSON.toJSONString(responseBean); | ||
66 | +// return bufferFactory.wrap(json.getBytes()); | ||
67 | +// } | ||
68 | +// }); | ||
69 | +// return super.writeWith(re); | ||
70 | +// } | ||
71 | +// return super.writeWith(body); | ||
72 | +// } | ||
73 | +// }; | ||
74 | +// return chain.filter(exchange.mutate().response(decorator).build()); | ||
75 | + return chain.filter(exchange); | ||
76 | + } | ||
77 | + | ||
78 | + @Override | ||
79 | + public int getOrder() { | ||
80 | + return -2; | ||
81 | + } | ||
82 | + | ||
83 | + public boolean UrlFilter(ServerHttpRequest request) { | ||
84 | + boolean flag = false; | ||
85 | + String token = ""; | ||
86 | + if (!request.getPath().toString().contains(LOGIN)) { | ||
87 | + token = request.getHeaders().get("Authorization").toString(); | ||
88 | + token = token.substring(1, token.length() - 1); | ||
89 | + } | ||
90 | + String redisKey = token.replace("Bearer ", ""); | ||
91 | + String json = stringRedisTemplate.opsForValue().get(redisKey); | ||
92 | + if (json != null) { | ||
93 | + List<PERMISSION> permissionList = JsonToBean.jsonToUser(json); | ||
94 | + for (PERMISSION permission : permissionList) { | ||
95 | + if (pathMatcher.match(permission.getUrl(), request.getPath().toString())) { | ||
96 | + flag = true; | ||
97 | + break; | ||
98 | + } | ||
99 | + } | ||
100 | + } | ||
101 | + return flag; | ||
102 | + } | ||
103 | +} |
1 | +package com.example.gateway.model; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +import java.util.List; | ||
6 | + | ||
7 | +@Data | ||
8 | +public class PERMISSION { | ||
9 | + private Integer permissionId; | ||
10 | + | ||
11 | + private String name; | ||
12 | + | ||
13 | + private String permissionOrder; | ||
14 | + | ||
15 | + private String description; | ||
16 | + | ||
17 | + private Boolean ismenu; | ||
18 | + | ||
19 | + private Boolean hidden; | ||
20 | + | ||
21 | + private Integer parentId; | ||
22 | + | ||
23 | + private String path; | ||
24 | + | ||
25 | + private String url; | ||
26 | + | ||
27 | + private String method; | ||
28 | + | ||
29 | + private String iconCls; | ||
30 | + | ||
31 | + private String component; | ||
32 | + | ||
33 | + private List<PERMISSION> children; | ||
34 | + | ||
35 | +} |
1 | +package com.example.gateway.model; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +import java.util.List; | ||
6 | + | ||
7 | +@Data | ||
8 | +public class ROLE { | ||
9 | + | ||
10 | + private Integer roleId; | ||
11 | + | ||
12 | + private String roleName; | ||
13 | + | ||
14 | + private String roleSign; | ||
15 | + | ||
16 | + private String description; | ||
17 | + | ||
18 | + private List<PERMISSION> permissions; | ||
19 | + | ||
20 | + public Integer getRoleId() { | ||
21 | + return roleId; | ||
22 | + } | ||
23 | + | ||
24 | + public void setRoleId(Integer roleId) { | ||
25 | + this.roleId = roleId; | ||
26 | + } | ||
27 | + | ||
28 | + public String getRoleName() { | ||
29 | + return roleName; | ||
30 | + } | ||
31 | + | ||
32 | + public void setRoleName(String roleName) { | ||
33 | + this.roleName = roleName == null ? null : roleName.trim(); | ||
34 | + } | ||
35 | + | ||
36 | + public String getRoleSign() { | ||
37 | + return roleSign; | ||
38 | + } | ||
39 | + | ||
40 | + public void setRoleSign(String roleSign) { | ||
41 | + this.roleSign = roleSign == null ? null : roleSign.trim(); | ||
42 | + } | ||
43 | + | ||
44 | + public String getDescription() { | ||
45 | + return description; | ||
46 | + } | ||
47 | + | ||
48 | + public void setDescription(String description) { | ||
49 | + this.description = description == null ? null : description.trim(); | ||
50 | + } | ||
51 | + | ||
52 | + public List<PERMISSION> getPermissions() { | ||
53 | + return permissions; | ||
54 | + } | ||
55 | + | ||
56 | + public void setPermissions(List<PERMISSION> permissions) { | ||
57 | + this.permissions = permissions; | ||
58 | + } | ||
59 | + | ||
60 | +} |
1 | +package com.example.gateway.model; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +import java.util.List; | ||
6 | + | ||
7 | +/** | ||
8 | + * @author | ||
9 | + * @time 2019-09-19 15:01 | ||
10 | + */ | ||
11 | +@Data | ||
12 | +public class ResponseBean<T> { | ||
13 | + | ||
14 | + private String code; | ||
15 | + | ||
16 | + private String message; | ||
17 | + | ||
18 | + private String error; | ||
19 | + | ||
20 | + private List<T> data; | ||
21 | + | ||
22 | + private String jwtToken; | ||
23 | + | ||
24 | + public ResponseBean(String code, String message, List<T> data) { | ||
25 | + this.code = code; | ||
26 | + this.message = message; | ||
27 | + this.data = data; | ||
28 | + } | ||
29 | + | ||
30 | + public ResponseBean(String code, String message, String error, List<T> data, String jwtToken) { | ||
31 | + this.code = code; | ||
32 | + this.message = message; | ||
33 | + this.error = error; | ||
34 | + this.data = data; | ||
35 | + this.jwtToken = jwtToken; | ||
36 | + } | ||
37 | +} |
1 | +package com.example.gateway.model; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +import java.util.Date; | ||
6 | +import java.util.List; | ||
7 | + | ||
8 | +@Data | ||
9 | +public class USERS { | ||
10 | + | ||
11 | + private static final long serialVersionUID = 1L; | ||
12 | + | ||
13 | + private Integer userId; | ||
14 | + private String username; | ||
15 | + | ||
16 | + private String password; | ||
17 | + | ||
18 | + private Date birthday; | ||
19 | + | ||
20 | + private String sex; | ||
21 | + | ||
22 | + private String address; | ||
23 | + | ||
24 | + private Boolean state; | ||
25 | + | ||
26 | + private String mobilephone; | ||
27 | + | ||
28 | + private Date creattime; | ||
29 | + | ||
30 | + private Date updatetime; | ||
31 | + | ||
32 | + private String userface; | ||
33 | + | ||
34 | + private String realname; | ||
35 | + | ||
36 | + private String email; | ||
37 | + | ||
38 | + private Integer age; | ||
39 | + | ||
40 | + private String token; | ||
41 | + | ||
42 | + private List<ROLE> roles; | ||
43 | + | ||
44 | + private List<PERMISSION> permissions; | ||
45 | + | ||
46 | +} |
1 | +package com.example.gateway.routerController; | ||
2 | + | ||
3 | +import com.example.gateway.routerImpl.DynamicRouteService; | ||
4 | +import org.springframework.beans.factory.annotation.Autowired; | ||
5 | +import org.springframework.cloud.gateway.route.RouteDefinition; | ||
6 | +import org.springframework.cloud.gateway.route.RouteDefinitionLocator; | ||
7 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
8 | +import org.springframework.web.bind.annotation.RestController; | ||
9 | +import reactor.core.publisher.Flux; | ||
10 | + | ||
11 | +/** | ||
12 | + * 查询网关的路由信息 | ||
13 | + */ | ||
14 | +@RestController | ||
15 | +@RequestMapping("/route") | ||
16 | +public class DynamicRouteController { | ||
17 | + | ||
18 | + @Autowired private RouteDefinitionLocator routeDefinitionLocator; | ||
19 | + @Autowired private DynamicRouteService dynamicRouteService; | ||
20 | + | ||
21 | + //获取网关所有的路由信息 | ||
22 | + @RequestMapping("/routes") | ||
23 | + public Flux<RouteDefinition> getRouteDefinitions(){ | ||
24 | + return routeDefinitionLocator.getRouteDefinitions(); | ||
25 | + } | ||
26 | + | ||
27 | +} |
1 | +package com.example.gateway.routerImpl; | ||
2 | + | ||
3 | +import org.springframework.beans.factory.annotation.Autowired; | ||
4 | +import org.springframework.cloud.gateway.event.RefreshRoutesEvent; | ||
5 | +import org.springframework.cloud.gateway.route.RouteDefinition; | ||
6 | +import org.springframework.cloud.gateway.route.RouteDefinitionWriter; | ||
7 | +import org.springframework.cloud.gateway.support.NotFoundException; | ||
8 | +import org.springframework.context.ApplicationEventPublisher; | ||
9 | +import org.springframework.context.ApplicationEventPublisherAware; | ||
10 | +import org.springframework.http.ResponseEntity; | ||
11 | +import org.springframework.stereotype.Component; | ||
12 | +import reactor.core.publisher.Mono; | ||
13 | + | ||
14 | +/** | ||
15 | + * 动态路由服务 | ||
16 | + */ | ||
17 | +@Component | ||
18 | +public class DynamicRouteService implements ApplicationEventPublisherAware { | ||
19 | + | ||
20 | + @Autowired | ||
21 | + private RouteDefinitionWriter routeDefinitionWriter; | ||
22 | + private ApplicationEventPublisher publisher; | ||
23 | + | ||
24 | + @Override | ||
25 | + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { | ||
26 | + this.publisher = applicationEventPublisher; | ||
27 | + } | ||
28 | + | ||
29 | + | ||
30 | + //增加路由 | ||
31 | + public String add(RouteDefinition definition) { | ||
32 | + routeDefinitionWriter.save(Mono.just(definition)).subscribe(); | ||
33 | + this.publisher.publishEvent(new RefreshRoutesEvent(this)); | ||
34 | + return "success"; | ||
35 | + } | ||
36 | + | ||
37 | + //更新路由 | ||
38 | + public String update(RouteDefinition definition) { | ||
39 | + try { | ||
40 | + delete(definition.getId()); | ||
41 | + } catch (Exception e) { | ||
42 | + return "update fail,not find route routeId: "+definition.getId(); | ||
43 | + } | ||
44 | + try { | ||
45 | + routeDefinitionWriter.save(Mono.just(definition)).subscribe(); | ||
46 | + this.publisher.publishEvent(new RefreshRoutesEvent(this)); | ||
47 | + return "success"; | ||
48 | + } catch (Exception e) { | ||
49 | + return "update route fail"; | ||
50 | + } | ||
51 | + } | ||
52 | + | ||
53 | + //删除路由 | ||
54 | + public Mono<ResponseEntity<Object>> delete(String id) { | ||
55 | + return this.routeDefinitionWriter.delete(Mono.just(id)).then(Mono.defer(() -> { | ||
56 | + return Mono.just(ResponseEntity.ok().build()); | ||
57 | + })).onErrorResume((t) -> { | ||
58 | + return t instanceof NotFoundException; | ||
59 | + }, (t) -> { | ||
60 | + return Mono.just(ResponseEntity.notFound().build()); | ||
61 | + }); | ||
62 | + } | ||
63 | +} |
1 | +package com.example.gateway.routerModel; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +import java.util.LinkedHashMap; | ||
6 | +import java.util.Map; | ||
7 | + | ||
8 | +/** | ||
9 | + * @author | ||
10 | + * @time 2019-09-12 15:52 | ||
11 | + * @Desc 路由断言模型 | ||
12 | + */ | ||
13 | +@Data | ||
14 | +public class GatewayFilterDefinition { | ||
15 | + | ||
16 | + //断言对应的name | ||
17 | + private String name; | ||
18 | + | ||
19 | + //路由断言规则 | ||
20 | + private Map<String, String> args = new LinkedHashMap<>(); | ||
21 | + | ||
22 | + | ||
23 | +} |
1 | +package com.example.gateway.routerModel; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +import java.util.LinkedHashMap; | ||
6 | +import java.util.Map; | ||
7 | + | ||
8 | +/** | ||
9 | + * @author | ||
10 | + * @time 2019-09-12 15:51 | ||
11 | + * @Desc 过滤器模型 | ||
12 | + */ | ||
13 | +@Data | ||
14 | +public class GatewayPredicateDefinition { | ||
15 | + | ||
16 | + //Filter Name | ||
17 | + private String name; | ||
18 | + | ||
19 | + //对应的路由规则 | ||
20 | + private Map<String, String> args = new LinkedHashMap<>(); | ||
21 | + | ||
22 | +} |
1 | +package com.example.gateway.routerModel; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +import java.util.ArrayList; | ||
6 | +import java.util.List; | ||
7 | + | ||
8 | +/** | ||
9 | + * @author | ||
10 | + * @time 2019-09-12 15:45 | ||
11 | + * @Desc 创建路由模型 | ||
12 | + */ | ||
13 | +@Data | ||
14 | +public class GatewayRouteDefinition { | ||
15 | + | ||
16 | + //路由过滤集合配置 | ||
17 | + private List<GatewayFilterDefinition> filters = new ArrayList<>(); | ||
18 | + | ||
19 | + //路由id | ||
20 | + private String id; | ||
21 | + | ||
22 | + //路由规则转发的目标URI | ||
23 | + private String uri; | ||
24 | + | ||
25 | + //路由执行的顺序 | ||
26 | + private int order = 0; | ||
27 | + | ||
28 | + //路由断言集合配置 | ||
29 | + private List<GatewayPredicateDefinition> predicates = new ArrayList<>(); | ||
30 | + | ||
31 | + | ||
32 | + | ||
33 | + | ||
34 | + | ||
35 | +} |
1 | +package com.example.gateway.scheduling; | ||
2 | + | ||
3 | +import com.alibaba.fastjson.JSON; | ||
4 | +import com.example.gateway.routerImpl.DynamicRouteService; | ||
5 | +import com.example.gateway.routerModel.GatewayFilterDefinition; | ||
6 | +import com.example.gateway.routerModel.GatewayPredicateDefinition; | ||
7 | +import com.example.gateway.routerModel.GatewayRouteDefinition; | ||
8 | +import org.springframework.beans.factory.annotation.Autowired; | ||
9 | +import org.springframework.cloud.gateway.filter.FilterDefinition; | ||
10 | +import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; | ||
11 | +import org.springframework.cloud.gateway.route.RouteDefinition; | ||
12 | +import org.springframework.scheduling.annotation.Scheduled; | ||
13 | +import org.springframework.stereotype.Component; | ||
14 | +import org.springframework.util.StringUtils; | ||
15 | +import org.springframework.web.client.RestTemplate; | ||
16 | +import org.springframework.web.util.UriComponentsBuilder; | ||
17 | + | ||
18 | +import java.net.URI; | ||
19 | +import java.text.SimpleDateFormat; | ||
20 | +import java.util.ArrayList; | ||
21 | +import java.util.Date; | ||
22 | +import java.util.List; | ||
23 | + | ||
24 | +/** | ||
25 | + * 定时任务,拉取路由信息 | ||
26 | + * 路由信息由路由项目单独维护 | ||
27 | + */ | ||
28 | +@Component | ||
29 | +public class DynamicRouteScheduling { | ||
30 | + | ||
31 | + @Autowired private RestTemplate restTemplate; | ||
32 | + @Autowired private DynamicRouteService dynamicRouteService; | ||
33 | + | ||
34 | + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||
35 | + private static final String dynamicRouteServerName = "dynamic-route"; | ||
36 | + | ||
37 | + //发布路由信息的版本号 | ||
38 | + private static Long versionId = 0L; | ||
39 | + | ||
40 | + //每60秒中执行一次 | ||
41 | + //如果版本号不相等则获取最新路由信息并更新网关路由 | ||
42 | + @Scheduled(cron = "*/60 * * * * ?") | ||
43 | + public void getDynamicRouteInfo(){ | ||
44 | + try{ | ||
45 | + System.out.println("拉取时间:" + dateFormat.format(new Date())); | ||
46 | + //先拉取版本信息,如果版本号不想等则更新路由 | ||
47 | + Long resultVersionId = restTemplate.getForObject("http://"+ dynamicRouteServerName +"/version/lastVersion" , Long.class); | ||
48 | + System.out.println("路由版本信息:本地版本号:" + versionId + ",远程版本号:" + resultVersionId); | ||
49 | + if(resultVersionId != null && versionId != resultVersionId){ | ||
50 | + System.out.println("开始拉取路由信息......"); | ||
51 | + String resultRoutes = restTemplate.getForObject("http://"+ dynamicRouteServerName +"/gateway-routes/routes" , String.class); | ||
52 | + System.out.println("路由信息为:" + resultRoutes); | ||
53 | + if(!StringUtils.isEmpty(resultRoutes)){ | ||
54 | + List<GatewayRouteDefinition> list = JSON.parseArray(resultRoutes , GatewayRouteDefinition.class); | ||
55 | + for(GatewayRouteDefinition definition : list){ | ||
56 | + //更新路由 | ||
57 | + RouteDefinition routeDefinition = assembleRouteDefinition(definition); | ||
58 | + dynamicRouteService.update(routeDefinition); | ||
59 | + } | ||
60 | + versionId = resultVersionId; | ||
61 | + } | ||
62 | + } | ||
63 | + }catch (Exception e){ | ||
64 | + e.printStackTrace(); | ||
65 | + } | ||
66 | + } | ||
67 | + | ||
68 | + | ||
69 | + //把前端传递的参数转换成路由对象 | ||
70 | + private RouteDefinition assembleRouteDefinition(GatewayRouteDefinition gwdefinition) { | ||
71 | + RouteDefinition definition = new RouteDefinition(); | ||
72 | + definition.setId(gwdefinition.getId()); | ||
73 | + definition.setOrder(gwdefinition.getOrder()); | ||
74 | + //设置断言 | ||
75 | + List<PredicateDefinition> pdList=new ArrayList<>(); | ||
76 | + List<GatewayPredicateDefinition> gatewayPredicateDefinitionList=gwdefinition.getPredicates(); | ||
77 | + for (GatewayPredicateDefinition gpDefinition: gatewayPredicateDefinitionList) { | ||
78 | + PredicateDefinition predicate = new PredicateDefinition(); | ||
79 | + predicate.setArgs(gpDefinition.getArgs()); | ||
80 | + predicate.setName(gpDefinition.getName()); | ||
81 | + pdList.add(predicate); | ||
82 | + } | ||
83 | + definition.setPredicates(pdList); | ||
84 | + | ||
85 | + //设置过滤器 | ||
86 | + List<FilterDefinition> filters = new ArrayList(); | ||
87 | + List<GatewayFilterDefinition> gatewayFilters = gwdefinition.getFilters(); | ||
88 | + for(GatewayFilterDefinition filterDefinition : gatewayFilters){ | ||
89 | + FilterDefinition filter = new FilterDefinition(); | ||
90 | + filter.setName(filterDefinition.getName()); | ||
91 | + filter.setArgs(filterDefinition.getArgs()); | ||
92 | + filters.add(filter); | ||
93 | + } | ||
94 | + definition.setFilters(filters); | ||
95 | + | ||
96 | + URI uri = null; | ||
97 | + if(gwdefinition.getUri().startsWith("http")){ | ||
98 | + uri = UriComponentsBuilder.fromHttpUrl(gwdefinition.getUri()).build().toUri(); | ||
99 | + }else{ | ||
100 | + uri = URI.create(gwdefinition.getUri()); | ||
101 | + } | ||
102 | + definition.setUri(uri); | ||
103 | + return definition; | ||
104 | + } | ||
105 | +} | ||
106 | + |
1 | +package com.example.gateway.util; | ||
2 | + | ||
3 | + | ||
4 | +import com.alibaba.fastjson.JSONObject; | ||
5 | +import com.example.gateway.model.PERMISSION; | ||
6 | +import com.example.gateway.model.USERS; | ||
7 | + | ||
8 | +import java.util.ArrayList; | ||
9 | +import java.util.List; | ||
10 | + | ||
11 | +/** | ||
12 | + * @author | ||
13 | + * @time 2019-09-18 15:58 | ||
14 | + */ | ||
15 | +public class JsonToBean { | ||
16 | + | ||
17 | + public static List<PERMISSION> jsonToUser(String json){ | ||
18 | + json = json.replace("USERS",""); | ||
19 | + JSONObject jsonObject = JSONObject.parseObject(json); | ||
20 | + USERS users = JSONObject.toJavaObject(jsonObject,USERS.class); | ||
21 | + List<PERMISSION> list = users.getPermissions(); | ||
22 | + List<PERMISSION> permissionList = new ArrayList<>(); | ||
23 | + for (PERMISSION permission: list){ | ||
24 | + permissionList.add(permission); | ||
25 | + } | ||
26 | + return permissionList; | ||
27 | + } | ||
28 | +} |
src/main/resources/application.yml
0 → 100644
1 | +spring: | ||
2 | + redis: | ||
3 | + host: localhost | ||
4 | + port: 6379 | ||
5 | + timeout: 60000 | ||
6 | + application: | ||
7 | + name: gateway-server | ||
8 | + main: | ||
9 | + allow-bean-definition-overriding: true | ||
10 | + cloud: # spring cloud gateway 路由配置方式 | ||
11 | + gateway: | ||
12 | + discovery: #是否与服务发现组件进行结合,通过 serviceId(必须设置成大写) 转发到具体的服务实例。默认为false,设为true便开启通过服务中心的自动根据 serviceId 创建路由的功能。 | ||
13 | + locator: #路由访问方式:http://Gateway_HOST:Gateway_PORT/大写的serviceId/**, | ||
14 | + lower-case-service-id: true #其中微服务应用名默认大写访问,设置此属性可小写访问。 | ||
15 | + enabled: true #gateway生成默认的routes,true生成,false,不生成 | ||
16 | + routes: | ||
17 | +# - id: ORDER-SERVICE #网关路由到订单服务order-service | ||
18 | +# uri: lb://ORDER-SERVICE #//后必须跟注册中心服务名称,表示跳转服务 | ||
19 | +# predicates: | ||
20 | +# - Path=/order/** | ||
21 | +# - id: USE-SERVICE #网关路由到用户服务user-service | ||
22 | +# uri: lb://USE-SERVICE | ||
23 | +# predicates: | ||
24 | +# - Path=/use/** | ||
25 | +# - id: nmms | ||
26 | +# uri: lb://WLPT-NMMS | ||
27 | +# predicates: | ||
28 | +# - Path=/nmms/** | ||
29 | +# filters: | ||
30 | +# - StripPrefix=1 | ||
31 | +# - id: awba-server | ||
32 | +# uri: lb://awba-server | ||
33 | +# predicates: | ||
34 | +# - Path=/awb/** | ||
35 | +# filters: | ||
36 | +# - StripPrefix=1 | ||
37 | +server: | ||
38 | + port: 12343 | ||
39 | + | ||
40 | +eureka: | ||
41 | + client: | ||
42 | + service-url: | ||
43 | +# defaultZone: http://192.168.1.53:12345/eureka/ | ||
44 | + defaultZone: http://localhost:12345/eureka/ | ||
45 | + healthcheck: | ||
46 | + enabled: true | ||
47 | +# instance: | ||
48 | +# #eureka服务器页面中status的请求路径 | ||
49 | +# status-page-url: http://${eureka.instance.hostname}:${server.port}/index | ||
50 | +# prefer-ip-address: true | ||
51 | +# instance-id: ${spring.cloud.client.ip-address}:${server.port} | ||
52 | +# hostname: ${spring.cloud.client.ip-address} | ||
53 | +# lease-renewal-interval-in-seconds: 15 | ||
54 | +# lease-expiration-duration-in-seconds: 45 | ||
55 | + | ||
56 | +#日志配置 | ||
57 | +logging: | ||
58 | + config: classpath:logback-spring.xml | ||
59 | +logback: | ||
60 | + appname: gateway-service | ||
61 | + logdir: ./log | ||
62 | +# 暴露端点 | ||
63 | +management: | ||
64 | + endpoints: | ||
65 | + web: | ||
66 | + exposure: | ||
67 | + include: '*' | ||
68 | + endpoint: | ||
69 | + health: | ||
70 | + show-details: always | ||
71 | + |
src/main/resources/logback-spring.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<configuration scan="ture" scanPeriod="60 seconds" debug="false"> | ||
3 | + | ||
4 | + <springProperty scope="context" name="appname" source="logback.appname"/> | ||
5 | + <springProperty scope="context" name="logdir" source="logback.logdir"/> | ||
6 | + <!--文件名--> | ||
7 | + <contextName>${logback.appname}</contextName> | ||
8 | + | ||
9 | + <!--输出到控制面板--> | ||
10 | + <appender name="consoleLog1" class="ch.qos.logback.core.ConsoleAppender"> | ||
11 | + <!-- layout输出方式输出--> | ||
12 | + <layout class="ch.qos.logback.classic.PatternLayout"> | ||
13 | + <pattern>%d [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
14 | + </layout> | ||
15 | + </appender> | ||
16 | + <!--输出到控制面板--> | ||
17 | + <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"> | ||
18 | + <encoder> | ||
19 | + <pattern>%d [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
20 | + </encoder> | ||
21 | + </appender> | ||
22 | + <!--输出info级别日志--> | ||
23 | + <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||
24 | + <filter class="ch.qos.logback.classic.filter.LevelFilter"> | ||
25 | + <!--过滤 Error--> | ||
26 | + <level>ERROR</level> | ||
27 | + <!--匹配到就禁止--> | ||
28 | + <onMatch>DENY</onMatch> | ||
29 | + <!--没有匹配到就允许--> | ||
30 | + <onMismatch>ACCEPT</onMismatch> | ||
31 | + </filter> | ||
32 | + <!--<File>../logs</File>--> | ||
33 | + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | ||
34 | + <FileNamePattern>${logdir}/info.${appname}.%d{yyyy-MM-dd}.log</FileNamePattern> | ||
35 | + <maxHistory>100</maxHistory> | ||
36 | + <totalSizeCap>100MB</totalSizeCap> | ||
37 | + </rollingPolicy> | ||
38 | + <encoder> | ||
39 | + <charset>UTF-8</charset> | ||
40 | + <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern> | ||
41 | + </encoder> | ||
42 | + </appender> | ||
43 | + <!--输出Error级别日志--> | ||
44 | + <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||
45 | + <filter class="ch.qos.logback.classic.filter.LevelFilter"> | ||
46 | + <!--过滤 Error --> | ||
47 | + <level>ERROR</level> | ||
48 | + </filter> | ||
49 | + <!--<File>../logs</File>--> | ||
50 | + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | ||
51 | + <FileNamePattern>${logdir}/error.${appname}.%d{yyyy-MM-dd}.log</FileNamePattern> | ||
52 | + <maxHistory>100</maxHistory> | ||
53 | + <totalSizeCap>100MB</totalSizeCap> | ||
54 | + </rollingPolicy> | ||
55 | + <encoder> | ||
56 | + <charset>UTF-8</charset> | ||
57 | + <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern> | ||
58 | + </encoder> | ||
59 | + </appender> | ||
60 | + <!--监控下列类的所有日志,定义输出级别--> | ||
61 | + <logger name="java.sql.PreparedStatement" level="DEBUG" additivity="false"> | ||
62 | + <appender-ref ref="consoleLog"/> | ||
63 | + </logger> | ||
64 | + <logger name="java.sql.Connection" level="DEBUG" additivity="false"> | ||
65 | + <appender-ref ref="consoleLog"/> | ||
66 | + </logger> | ||
67 | + <logger name="java.sql.Statement" level="DEBUG" additivity="false"> | ||
68 | + <appender-ref ref="consoleLog"/> | ||
69 | + </logger> | ||
70 | + <logger name="com.ibatis" level="DEBUG" additivity="false"> | ||
71 | + <appender-ref ref="consoleLog"/> | ||
72 | + </logger> | ||
73 | + <logger name="com.ibatis.common.jdbc.SimpleDataSource" level="DEBUG" additivity="false"> | ||
74 | + <appender-ref ref="consoleLog"/> | ||
75 | + </logger> | ||
76 | + <logger name="com.ibatis.common.jdbc.ScriptRunner" level="DEBUG" additivity="false"> | ||
77 | + <appender-ref ref="consoleLog"/> | ||
78 | + </logger> | ||
79 | + <logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" level="DEBUG" additivity="false"> | ||
80 | + <appender-ref ref="consoleLog"/> | ||
81 | + </logger> | ||
82 | + <!--输出--> | ||
83 | + <root level="INFO"> | ||
84 | + <appender-ref ref="consoleLog1"/> | ||
85 | + <!--<appender-ref ref="consoleLog"/>--> | ||
86 | + <appender-ref ref="fileInfoLog"/> | ||
87 | + <!--<appender-ref ref="fileErrorLog"/>--> | ||
88 | + </root> | ||
89 | + | ||
90 | +</configuration> |
-
请 注册 或 登录 后发表评论