Browse Source

:sparkles: 添加新特性。gateway 动态路由

冷冷 6 năm trước cách đây
mục cha
commit
d7b4cbfa60

+ 10 - 22
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/support/DynamicRouteEndpoint.java

@@ -17,6 +17,7 @@
 
 package com.pig4cloud.pigx.gateway.support;
 
+import cn.hutool.json.JSONObject;
 import com.pig4cloud.pigx.common.core.util.R;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -50,36 +51,23 @@ public class DynamicRouteEndpoint {
 	}
 
 	/**
-	 * 新增路由
-	 *
-	 * @param route 路由定义
-	 * @return
-	 */
-	@PostMapping
-	public Mono<R> save(@RequestBody Mono<RouteDefinition> route) {
-		return Mono.just(new R(dynamicRouteHandler.addRoute(route)));
-	}
-
-	/**
-	 * 删除路由
+	 * 修改路由
 	 *
-	 * @param id 路由定义ID
+	 * @param routes 路由定义
 	 * @return
 	 */
-	@DeleteMapping("/{id}")
-	public Mono<R> delete(@PathVariable String id) {
-		return Mono.just(new R(dynamicRouteHandler.deleteRoute(id)));
-
+	@PutMapping
+	public R edit(@RequestBody JSONObject routes) {
+		return new R(dynamicRouteHandler.editRoutes(routes));
 	}
 
 	/**
-	 * 修改路由
+	 * 回滚初始化配置
 	 *
-	 * @param routeDefinition 路由定义
 	 * @return
 	 */
-	@PutMapping
-	public R edit(@RequestBody RouteDefinition routeDefinition) {
-		return new R();
+	@GetMapping("/fallback")
+	public Mono<R> fallback() {
+		return Mono.just(new R(dynamicRouteHandler.fallback()));
 	}
 }

+ 68 - 11
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/support/DynamicRouteHandler.java

@@ -17,16 +17,25 @@
 
 package com.pig4cloud.pigx.gateway.support;
 
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import com.pig4cloud.pigx.common.core.constant.CommonConstant;
+import com.pig4cloud.pigx.gateway.support.vo.RouteDefinitionVo;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
+import org.springframework.cloud.gateway.filter.FilterDefinition;
+import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
 import org.springframework.cloud.gateway.route.RouteDefinition;
 import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
-import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.context.ApplicationEventPublisherAware;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
 import org.springframework.stereotype.Service;
 import reactor.core.publisher.Mono;
 
+import java.net.URI;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -39,13 +48,13 @@ import java.util.Map;
 @Slf4j
 @Service
 public class DynamicRouteHandler implements ApplicationEventPublisherAware {
-	private final RouteDefinitionWriter routeDefinitionWriter;
 	private final RouteDefinitionLocator routeDefinitionLocator;
+	private final RedisTemplate redisTemplate;
 	private ApplicationEventPublisher applicationEventPublisher;
 
-	public DynamicRouteHandler(RouteDefinitionWriter routeDefinitionWriter
+	public DynamicRouteHandler(RedisTemplate redisTemplate
 		, RouteDefinitionLocator routeDefinitionLocator) {
-		this.routeDefinitionWriter = routeDefinitionWriter;
+		this.redisTemplate = redisTemplate;
 		this.routeDefinitionLocator = routeDefinitionLocator;
 	}
 
@@ -63,19 +72,67 @@ public class DynamicRouteHandler implements ApplicationEventPublisherAware {
 	}
 
 	/**
-	 * 添加路由
+	 * 更新路由信息
 	 *
-	 * @param route 路由定义
+	 * @param routes 路由信息
 	 * @return
 	 */
-	public Mono<Void> addRoute(Mono<RouteDefinition> route) {
+	public Mono<Void> editRoutes(JSONObject routes) {
+		Boolean result = redisTemplate.delete(CommonConstant.ROUTE_KEY);
+		log.info("清空网关路由 {} ", result);
+
+		routes.forEach((key, value) -> {
+			log.info("更新路由 -> {} ->{}", key, value);
+			RouteDefinitionVo vo = new RouteDefinitionVo();
+			Map<String, Object> map = (Map) value;
+
+			Object id = map.get("id");
+			if (id != null) {
+				vo.setId(String.valueOf(id));
+			}
+
+			Object predicates = map.get("predicates");
+			if (predicates != null) {
+				JSONArray predicatesArray = (JSONArray) predicates;
+				List<PredicateDefinition> predicateDefinitionList =
+					predicatesArray.toList(PredicateDefinition.class);
+				vo.setPredicates(predicateDefinitionList);
+			}
+
+			Object filters = map.get("filters");
+			if (filters != null) {
+				JSONArray filtersArray = (JSONArray) filters;
+				List<FilterDefinition> filterDefinitionList
+					= filtersArray.toList(FilterDefinition.class);
+				vo.setFilters(filterDefinitionList);
+			}
+
+			Object uri = map.get("uri");
+			if (uri != null) {
+				vo.setUri(URI.create(String.valueOf(uri)));
+			}
+
+			Object order = map.get("order");
+			if (order != null) {
+				vo.setOrder(Integer.parseInt(String.valueOf(order)));
+			}
+
+			redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(RouteDefinitionVo.class));
+			redisTemplate.opsForHash().put(CommonConstant.ROUTE_KEY, key, vo);
+		});
+		log.debug("更新网关路由结束 ");
 		this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
-		return routeDefinitionWriter.save(route);
+		return Mono.empty();
 	}
 
-	public Mono<Void> deleteRoute(String id) {
-		this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
-		return routeDefinitionWriter.delete(Mono.just(id));
+	/**
+	 * 回滚路由
+	 *
+	 * @return
+	 */
+	public Mono<Void> fallback() {
+		this.applicationEventPublisher.publishEvent(new DynamicRouteInitEvent(this));
+		return Mono.empty();
 	}
 
 	@Override

+ 32 - 0
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/support/DynamicRouteInitEvent.java

@@ -0,0 +1,32 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.gateway.support;
+
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * @author lengleng
+ * @date 2018/11/5
+ * <p>
+ * 路由初始化事件
+ */
+public class DynamicRouteInitEvent extends ApplicationEvent {
+	public DynamicRouteInitEvent(Object source) {
+		super(source);
+	}
+}

+ 1 - 1
pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/support/DynamicRouteInitRunner.java

@@ -48,7 +48,7 @@ public class DynamicRouteInitRunner {
 
 	@Async
 	@Order
-	@EventListener(WebServerInitializedEvent.class)
+	@EventListener({WebServerInitializedEvent.class, DynamicRouteInitEvent.class})
 	public void initRoute() {
 		Boolean result = redisTemplate.delete(CommonConstant.ROUTE_KEY);
 		log.info("初始化网关路由 {} ", result);

+ 16 - 16
pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/MenuController.java

@@ -19,7 +19,6 @@
 
 package com.pig4cloud.pigx.admin.controller;
 
-import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.mapper.EntityWrapper;
 import com.pig4cloud.pigx.admin.api.dto.MenuTree;
 import com.pig4cloud.pigx.admin.api.entity.SysMenu;
@@ -34,7 +33,11 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
-import java.util.*;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @author lengleng
@@ -55,14 +58,13 @@ public class MenuController {
 	public List<MenuTree> userMenu() {
 		// 获取符合条件得菜单
 		Set<MenuVO> all = new HashSet<>();
-		SecurityUtils.getRoles().forEach(roleId -> all.addAll(sysMenuService.findMenuByRoleId(roleId)));
-		List<MenuTree> menuTreeList = new ArrayList<>();
-		all.forEach(menuVo -> {
-			if (CommonConstant.MENU.equals(menuVo.getType())) {
-				menuTreeList.add(new MenuTree(menuVo));
-			}
-		});
-		CollUtil.sort(menuTreeList, Comparator.comparingInt(MenuTree::getSort));
+		SecurityUtils.getRoles()
+			.forEach(roleId -> all.addAll(sysMenuService.findMenuByRoleId(roleId)));
+		List<MenuTree> menuTreeList = all.stream()
+			.filter(menuVo -> CommonConstant.MENU.equals(menuVo.getType()))
+			.map(MenuTree::new)
+			.sorted(Comparator.comparingInt(MenuTree::getSort))
+			.collect(Collectors.toList());
 		return TreeUtil.bulid(menuTreeList, -1);
 	}
 
@@ -86,12 +88,10 @@ public class MenuController {
 	 */
 	@GetMapping("/roleTree/{roleId}")
 	public List<Integer> roleTree(@PathVariable Integer roleId) {
-		List<MenuVO> menus = sysMenuService.findMenuByRoleId(roleId);
-		List<Integer> menuList = new ArrayList<>();
-		for (MenuVO menuVo : menus) {
-			menuList.add(menuVo.getMenuId());
-		}
-		return menuList;
+		return sysMenuService.findMenuByRoleId(roleId)
+			.stream()
+			.map(MenuVO::getMenuId)
+			.collect(Collectors.toList());
 	}
 
 	/**

+ 1 - 0
pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/UserController.java

@@ -110,6 +110,7 @@ public class UserController {
 
 	/**
 	 * 添加用户
+	 * TODO  什么鬼逻辑,先删除再增加???
 	 *
 	 * @param userDto 用户信息
 	 * @return success/false

+ 14 - 13
pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysLogServiceImpl.java

@@ -28,8 +28,8 @@ import com.pig4cloud.pigx.common.core.constant.CommonConstant;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
-import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -60,18 +60,19 @@ public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> impleme
 	 */
 	@Override
 	public Boolean insertLogs(List<PreLogVo> preLogVoList) {
-		List<SysLog> sysLogs = new ArrayList<>();
-		preLogVoList.forEach(pre -> {
-			SysLog log = new SysLog();
-			log.setType(CommonConstant.STATUS_LOCK);
-			log.setTitle(pre.getInfo());
-			log.setException(pre.getStack());
-			log.setParams(pre.getMessage());
-			log.setCreateTime(LocalDateTime.now());
-			log.setRequestUri(pre.getUrl());
-			log.setCreateBy(pre.getUser());
-			sysLogs.add(log);
-		});
+		List<SysLog> sysLogs = preLogVoList.stream()
+			.map(pre -> {
+				SysLog log = new SysLog();
+				log.setType(CommonConstant.STATUS_LOCK);
+				log.setTitle(pre.getInfo());
+				log.setException(pre.getStack());
+				log.setParams(pre.getMessage());
+				log.setCreateTime(LocalDateTime.now());
+				log.setRequestUri(pre.getUrl());
+				log.setCreateBy(pre.getUser());
+				return log;
+			})
+			.collect(Collectors.toList());
 		return this.insertBatch(sysLogs);
 	}
 }

+ 9 - 10
pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleMenuServiceImpl.java

@@ -30,9 +30,9 @@ import org.springframework.cache.CacheManager;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.stereotype.Service;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -64,15 +64,14 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
 			return Boolean.TRUE;
 		}
 
-		List<SysRoleMenu> roleMenuList = new ArrayList<>();
-		List<String> menuIdList = Arrays.asList(menuIds.split(","));
-
-		for (String menuId : menuIdList) {
-			SysRoleMenu roleMenu = new SysRoleMenu();
-			roleMenu.setRoleId(roleId);
-			roleMenu.setMenuId(Integer.valueOf(menuId));
-			roleMenuList.add(roleMenu);
-		}
+		List<SysRoleMenu> roleMenuList = Arrays
+			.stream(menuIds.split(","))
+			.map(menuId -> {
+				SysRoleMenu roleMenu = new SysRoleMenu();
+				roleMenu.setRoleId(roleId);
+				roleMenu.setMenuId(Integer.valueOf(menuId));
+				return roleMenu;
+			}).collect(Collectors.toList());
 
 		//清空userinfo
 		cacheManager.getCache("user_details").clear();

+ 20 - 26
pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysUserServiceImpl.java

@@ -19,7 +19,6 @@
 
 package com.pig4cloud.pigx.admin.service.impl;
 
-import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.mapper.EntityWrapper;
@@ -48,10 +47,10 @@ import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
-import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @author lengleng
@@ -94,26 +93,22 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
 		UserInfo userInfo = new UserInfo();
 		userInfo.setSysUser(sysUser);
 		//设置角色列表  (ID)
-		List<SysRole> roleList = sysRoleService.findRolesByUserId(sysUser.getUserId());
-		List<Integer> roleIds = new ArrayList<>();
-		if (CollUtil.isNotEmpty(roleList)) {
-			roleList.forEach(sysRole -> roleIds.add(sysRole.getRoleId()));
-		}
+		List<Integer> roleIds = sysRoleService.findRolesByUserId(sysUser.getUserId())
+			.stream()
+			.map(SysRole::getRoleId)
+			.collect(Collectors.toList());
 		userInfo.setRoles(ArrayUtil.toArray(roleIds, Integer.class));
 
 		//设置权限列表(menu.permission)
-		Set<MenuVO> menuVoSet = new HashSet<>();
-		for (Integer roleId : roleIds) {
-			List<MenuVO> menuVos = sysMenuService.findMenuByRoleId(roleId);
-			menuVoSet.addAll(menuVos);
-		}
 		Set<String> permissions = new HashSet<>();
-		for (MenuVO menuVo : menuVoSet) {
-			if (StringUtils.isNotEmpty(menuVo.getPermission())) {
-				String permission = menuVo.getPermission();
-				permissions.add(permission);
-			}
-		}
+		roleIds.forEach(roleId -> {
+			List<String> permissionList = sysMenuService.findMenuByRoleId(roleId)
+				.stream()
+				.filter(menuVo -> StringUtils.isNotEmpty(menuVo.getPermission()))
+				.map(MenuVO::getPermission)
+				.collect(Collectors.toList());
+			permissions.addAll(permissionList);
+		});
 		userInfo.setPermissions(ArrayUtil.toArray(permissions, String.class));
 		return userInfo;
 	}
@@ -160,7 +155,6 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
 	 */
 	@Override
 	public Boolean deleteSysUserByUsernameAndUserId(String username, Integer userId) {
-
 		sysUserMapper.deleteSysUserByUsernameAndUserId(username, userId);
 		SysUserRole condition = new SysUserRole();
 		condition.setUserId(userId);
@@ -257,14 +251,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
 	 */
 	private List<Integer> getChildDepts() {
 		Integer deptId = SecurityUtils.getUser().getDeptId();
-
 		//获取当前部门的子部门
-		SysDeptRelation deptRelation = new SysDeptRelation();
-		deptRelation.setAncestor(deptId);
-		List<SysDeptRelation> deptRelationList = sysDeptRelationService.selectList(new EntityWrapper<>(deptRelation));
-		List<Integer> deptIds = new ArrayList<>();
-		deptRelationList.forEach(sysDeptRelation -> deptIds.add(sysDeptRelation.getDescendant()));
-		return deptIds;
+		SysDeptRelation condition = new SysDeptRelation();
+		condition.setAncestor(deptId);
+		return sysDeptRelationService
+			.selectList(new EntityWrapper<>(condition))
+			.stream()
+			.map(SysDeptRelation::getDescendant)
+			.collect(Collectors.toList());
 	}
 
 }