Gateway动态路由
What?
前段时间买了个服务器,没怎么用,就跑了个在线获取IdeaCode
的程序。使用率不怎么高,这次准备在跑一个Gateway
网关,以后就把我所有的程序都接入到网关里。但是以前网关里的路由都是硬编码的形式写到配置文件里的,这就意味着我每发布一个程序都要重新打包部署一下网关。
程序猿的存在就是解决一些需要频繁操作的事件,所以要想办法解决硬编码路由的问题,所以我写了本篇Gateway
动态路由。
思路
Gateway
的路由配置有两种方式,一种是通过配置文件配置,一种是通过代码配置。我准备做一个类似于管理系统的系统来管理路由配置,所以要使用代码的方式配置路由。
在项目启动的时候从数据库读取配置并且存到Redis
中。Gateway
在初始化的时候从Redis
中获取配置。
开发前的准备
- 一台电脑(废话,没有电脑怎么开发)
- Nacos注册中心(路由转发需要用到)
- MySQL数据库(持久化的储存路由配置)
- Redis(路由配置缓存)
- JDK1.8(我是基于JDK1.8做的开发)
- Maven(现在可是Maven的天下,总不能一个一个的添加依赖吧)
预览
Github:https://github.com/Ys2025/gateway-backend
Start
1、初始化数据库
CREATE TABLE `gateway_route` (
`id` bigint NOT NULL,
`route_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`uri` varchar(255) NOT NULL,
`predicates` varchar(255) NOT NULL,
`filters` varchar(255) DEFAULT NULL,
`ord` int DEFAULT '0',
`remarks` varchar(255) DEFAULT NULL,
`create_time` date DEFAULT NULL,
`update_time` date DEFAULT NULL,
`is_deleted` int DEFAULT '0',
`version` int DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
2、创建一个Gateway项目
启动类
package cn.yanghuisen.gateway;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@MapperScan("cn.yanghuisen.gateway.mapper")
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.yanghuisen</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 8080
spring:
application:
name: GATEWAY
cloud:
nacos:
discovery:
server-addr: localhost:8848
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/gateway_route?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
username: root
password: 123456
redis:
# Redis地址
host: localhost
# Redis端口
port: 6379
# RedisDB库
database: 0
# 链接超市
timeout: 10000ms
lettuce:
pool:
# 最大连接数
max-active: 1024
# 最大阻塞等待时间
max-wait: 10000ms
# 最大空闲时间
max-idle: 200
# 最小空闲链接
min-idle: 5
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-value: 1 # 逻辑已经删除的值(默认为1)
logic-not-delete-value: 0 # 逻辑没有删除的值(默认为0)
3、配置Redis
package cn.yanghuisen.gateway.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author admin
* @version 1.0
* @date 2020/5/14 20:52
* @Description 自定义模板
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory){
// 创建模板
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
// 设置String类型的Key的序列器
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置String类型的value的序列器
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// 设置Hash类型的Key的序列器
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// 设置hash类型的value的序列器
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
// 设置连接方式
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
return redisTemplate;
}
}
4、自定义路由储存库(核心1)
此类用于从
Redis
获取路由配置信息,以及监听的路由保存和删除
package cn.yanghuisen.gateway.config;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
/**
* @author Y
* @date 2020/11/28 0:02
* @desc 自定义路由储存库
*/
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
private static final String GATEWAY_ROUTES = "gateway:routes";
/**
* 获取路由信息,此处从Redis获取路由配置信息
* @return
*/
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
List<RouteDefinition> routeDefinitions = new ArrayList<>();
// 获取Redis中配置的路由信息
List<Object> routes = redisTemplate.opsForHash().values(GATEWAY_ROUTES);
// 遍历路由
routes.forEach(route->{
// 把json反序列话为RouteDefinition类对象
RouteDefinition routeDefinition = JSON.parseObject(route.toString(), RouteDefinition.class);
routeDefinitions.add(routeDefinition);
});
return Flux.fromIterable(routeDefinitions);
}
/**
* 添加路由
* @param route
* @return
*/
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(routeDefinition -> {
// 把路由信息存到Redis中
redisTemplate.opsForHash().put(GATEWAY_ROUTES,routeDefinition.getId(), JSON.toJSONString(routeDefinition));
return Mono.empty();
});
}
/**
* 删除路由
* @param routeId
* @return
*/
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id -> {
// 判断redis中是否有该id的路由数据
if (redisTemplate.opsForHash().hasKey(GATEWAY_ROUTES,id)){
// 删除数据
redisTemplate.opsForHash().delete(GATEWAY_ROUTES,id);
return Mono.empty();
}
return Mono.defer(()-> Mono.error(new NotFoundException("Redis中没有该路由:"+id)));
});
}
}
5、SpringBoot启动配置(核心2)
此类用于在
SpringBoot
启动的时候从数据库读取路由配置信息,并且把信息储存到Redis
中。以及发布路由的增删改事件
package cn.yanghuisen.gateway.handler;
import cn.yanghuisen.gateway.dto.GatewayRouteDTO;
import cn.yanghuisen.gateway.entity.GatewayRoute;
import cn.yanghuisen.gateway.mapper.GatewayRouteMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
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.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Y
* @date 2020/11/28 0:38
* @desc
*/
@Slf4j
@Component
public class GatewayServiceHandler implements ApplicationEventPublisherAware, CommandLineRunner {
private static final String GATEWAY_ROUTES = "gateway:routes";
private ApplicationEventPublisher publisher;
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private GatewayRouteMapper gatewayRouteMapper;
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
/**
* 项目启动的时候执行
* @param args
* @throws Exception
*/
@Override
public void run(String... args) throws Exception {
// 记载路由配置
this.loadRouteConfig();
}
public String loadRouteConfig(){
log.info("开始加载网关路由配置信息");
// 删除Redis里的路由配置信息
redisTemplate.delete(GATEWAY_ROUTES);
// 从数据库查询数据
List<GatewayRoute> gatewayRoutes = gatewayRouteMapper.selectList(null);
gatewayRoutes.forEach(gatewayRoute -> {
RouteDefinition definition = handleData(gatewayRoute);
// 保存路由
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
});
// 发布事件,通知更新数据
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
/**
* 保存路由
* @param dto
*/
public void saveRoute(GatewayRouteDTO dto){
GatewayRoute gatewayRoute = new GatewayRoute();
BeanUtils.copyProperties(dto,gatewayRoute);
// GatewayRoute转为RouteDefinition
RouteDefinition definition = handleData(gatewayRoute);
// 保存路由数据
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
// 发布事件,通知更新数据
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
/**
* 更新路由
* @param dto
*/
public void updateRoute(GatewayRouteDTO dto){
GatewayRoute gatewayRoute = new GatewayRoute();
BeanUtils.copyProperties(dto,gatewayRoute);
// GatewayRoute转为RouteDefinition
RouteDefinition definition = handleData(gatewayRoute);
// 根据路由ID删除路由信息
routeDefinitionWriter.delete(Mono.just(dto.getOldRouteId())).subscribe();
// 重新保存路由数据
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
// 发布事件,通知更新数据
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
/**
* 删除路由
* @param routeId
*/
public void deleteRoute(String routeId){
// 根据路由ID删除路由信息
routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
// 发布事件,通知更新数据
this.publisher.publishEvent(new RefreshRoutesEvent(this));
log.info("删除完毕");
}
/**
* GatewayRoute转RouteDefinition
* @param gatewayRoute
* @return
*/
public RouteDefinition handleData(GatewayRoute gatewayRoute){
RouteDefinition routeDefinition = new RouteDefinition();
URI uri = null;
// 判断Uri是不是http地址
if (gatewayRoute.getUri().startsWith("http")){
// http地址
uri = UriComponentsBuilder.fromHttpUrl(gatewayRoute.getUri()).build().toUri();
}else {
// 微服务服务名
uri = UriComponentsBuilder.fromUriString("lb://"+gatewayRoute.getUri()).build().toUri();
}
// 设置路由ID
routeDefinition.setId(gatewayRoute.getRouteId());
// 设置uri
routeDefinition.setUri(uri);
//谓语(路由转发条件)
PredicateDefinition predicate = new PredicateDefinition();
predicate.setName("Path");
Map<String,String> predicateArgs = new HashMap<>();
predicateArgs.put("pattern",gatewayRoute.getPredicates());
predicate.setArgs(predicateArgs);
routeDefinition.setPredicates(Collections.singletonList(predicate));
// 设置ord
if (null!=gatewayRoute.getOrd()){
routeDefinition.setOrder(gatewayRoute.getOrd());
}
return routeDefinition;
}
}
6、创建entity和DTO类
package cn.yanghuisen.gateway.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* @author Y
* @date 2020/11/28 1:16
* @desc 实体类
*/
@Data
public class GatewayRoute {
@TableId(type = IdType.ASSIGN_ID)
private String id;
private String routeId;
private String uri;
private String predicates;
private String filters;
private Integer ord;
private String remarks;
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd")
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd")
private Date updateTime;
/**
* 逻辑删除
*/
@TableLogic
private Integer isDeleted;
/**
* 乐观锁
*/
@Version
private Integer version;
}
package cn.yanghuisen.gateway.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* @author Y
* @date 2020/11/28 1:16
* @desc DTO类
*/
@Data
public class GatewayRouteDTO {
private String id;
private String routeId;
private String oldRouteId;
private String uri;
private String predicates;
private String filters;
private Integer ord;
private String remarks;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date updateTime;
private Integer isDeleted;
private Integer version;
}
7、创建Service层接口
package cn.yanghuisen.gateway.service;
import cn.yanghuisen.gateway.dto.GatewayRouteDTO;
import java.util.List;
/**
* @author Y
* @date 2020/11/28 22:38
* @desc
*/
public interface IRouteService {
/**
* 添加路由
* @param dto
* @return
*/
Integer add(GatewayRouteDTO dto);
/**
* 更新路由
* @param dto
* @return
*/
Integer update(GatewayRouteDTO dto);
/**
* 删除路由
* @param routeId
* @return
*/
Integer delete(String routeId);
/**
* 获取列表
* @return
*/
List<GatewayRouteDTO> list();
}
package cn.yanghuisen.gateway.service.impl;
import cn.yanghuisen.gateway.dto.GatewayRouteDTO;
import cn.yanghuisen.gateway.entity.GatewayRoute;
import cn.yanghuisen.gateway.mapper.GatewayRouteMapper;
import cn.yanghuisen.gateway.service.IRouteService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @author Y
* @date 2020/11/28 22:40
* @desc
*/
@Service
public class RouteServiceImpl implements IRouteService {
@Autowired
private GatewayRouteMapper routeMapper;
@Override
public Integer add(GatewayRouteDTO dto) {
GatewayRoute gatewayRoute = new GatewayRoute();
BeanUtils.copyProperties(dto,gatewayRoute);
return routeMapper.insert(gatewayRoute);
}
@Override
public Integer update(GatewayRouteDTO dto) {
GatewayRoute gatewayRoute = new GatewayRoute();
BeanUtils.copyProperties(dto,gatewayRoute);
return routeMapper.updateById(gatewayRoute);
}
@Override
public Integer delete(String routeId) {
QueryWrapper<GatewayRoute> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("route_id",routeId);
return routeMapper.delete(queryWrapper);
}
@Override
public List<GatewayRouteDTO> list() {
List<GatewayRouteDTO> result = new ArrayList<>();
List<GatewayRoute> gatewayRoutes = routeMapper.selectList(null);
gatewayRoutes.forEach(gatewayRoute -> {
GatewayRouteDTO dto = new GatewayRouteDTO();
BeanUtils.copyProperties(gatewayRoute,dto);
dto.setOldRouteId(gatewayRoute.getRouteId());
result.add(dto);
});
return result;
}
}
8、controller接口
package cn.yanghuisen.gateway.controller;
import cn.yanghuisen.gateway.dto.GatewayRouteDTO;
import cn.yanghuisen.gateway.handler.GatewayServiceHandler;
import cn.yanghuisen.gateway.service.IRouteService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author Y
* @date 2020/11/28 22:28
* @desc 路由API接口
*/
@RestController
@RequestMapping("/route")
@CrossOrigin
public class RouteController {
@Autowired
private GatewayServiceHandler gatewayServiceHandler;
@Autowired
private IRouteService routeService;
/**
* 刷新路由配置
* @return
*/
@GetMapping("/refresh")
public String refresh(){
return this.gatewayServiceHandler.loadRouteConfig();
}
/**
* 添加路由配置
* @param dto
* @return
*/
@PostMapping("/save")
public String add(@RequestBody GatewayRouteDTO dto){
if (StringUtils.isNotBlank(dto.getId())){
this.gatewayServiceHandler.updateRoute(dto);
this.routeService.update(dto);
}else {
this.gatewayServiceHandler.saveRoute(dto);
this.routeService.add(dto);
}
return "success";
}
@GetMapping("/delete")
public String delete(String routeId){
this.gatewayServiceHandler.deleteRoute(routeId);
this.routeService.delete(routeId);
return "success";
}
@GetMapping("/list")
public List<GatewayRouteDTO> list(){
return this.routeService.list();
}
}
9、前端代码
<template>
<div>
<el-row>
<el-button type="primary" icon="el-icon-circle-plus-outline" @click="addRoute">新增路由</el-button>
<el-button type="success" icon="el-icon-refresh" @click="refreshRoute">刷新路由</el-button>
</el-row>
<el-table
:data="tableData"
:row-class-name="tableRowClassName">
<el-table-column
prop="id"
label="ID"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="routeId"
label="routeId"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="uri"
label="uri"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="predicates"
label="predicates"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="filters"
label="filters"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="ord"
label="order"
width="150">
</el-table-column>
<el-table-column
prop="remarks"
label="remarks"
width="150">
</el-table-column>
<el-table-column
prop="createTime"
label="createTime"
width="150">
</el-table-column>
<el-table-column
prop="updateTime"
label="updateTime"
width="150">
</el-table-column>
<el-table-column
label="操作"
fixed="right"
width="150">
<template slot-scope="scope">
<el-button
size="mini"
@click="handleEdit(scope.row)">编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :title="dialogTitle" :visible.sync="dialogFormVisible">
<el-form :model="form" label-width="100px">
<el-form-item label="RouteId">
<el-input v-model="form.routeId"></el-input>
</el-form-item>
<el-form-item label="Uri">
<el-input v-model="form.uri"></el-input>
</el-form-item>
<el-form-item label="Predicates">
<el-input v-model="form.predicates"></el-input>
</el-form-item>
<el-form-item label="Filters">
<el-input v-model="form.filters"></el-input>
</el-form-item>
<el-form-item label="Order">
<el-input v-model="form.ord"></el-input>
</el-form-item>
<el-form-item label="Remarks">
<el-input type="textarea" v-model="form.remarks"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="clickDialog(form)">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data () {
return {
tableData: [],
dialogFormVisible: false,
form: {},
dialogTitle: '新增路由'
}
},
methods:{
tableRowClassName(data) {
console.log(data)
if (data.rowIndex%2){
return "warning-row"
}else {
return "success-row"
}
},
handleEdit(data) {
console.log(data);
this.dialogTitle='编辑路由'
this.dialogFormVisible = true
this.form = data
},
handleDelete(data) {
console.log(data);
this.$axios.get('http://localhost:8080/route/delete', {
params: {
routeId: data.routeId
}
}).then(result=> {
console.log(result);
this.getList()
})
},
clickDialog(data){
console.log(data)
this.$axios.post('http://localhost:8080/route/save', this.form).then(result=> {
console.log(result);
this.dialogFormVisible = false
this.getList()
})
},
refreshRoute(){
this.$axios.get('http://localhost:8080/route/refresh').then(result => {
console.log(result.data);
this.getList()
})
},
getList(){
this.$axios.get('http://localhost:8080/route/list').then(result => {
console.log(result.data);
this.tableData = result.data
})
},
addRoute(){
this.dialogTitle='新增路由'
this.dialogFormVisible = true
this.form = {}
}
},
created() {
console.log(1111)
this.getList()
}
}
</script>
<style>
.el-table .warning-row {
background: oldlace;
}
.el-table .success-row {
background: #f0f9eb;
}
</style>
时间原因,代码中没做必填校验。filters
暂时没用到,也没写。有空再补充吧。